bool CompositorPendingAnimations::startPendingAnimations()
{
    bool startedSynchronizedOnCompositor = false;
    for (size_t i = 0; i < m_pending.size(); ++i) {
        if (!m_pending[i]->hasActiveAnimationsOnCompositor() && m_pending[i]->maybeStartAnimationOnCompositor() && !m_pending[i]->hasStartTime())
            startedSynchronizedOnCompositor = true;
    }

    // If any synchronized animations were started on the compositor, all
    // remaning synchronized animations need to wait for the synchronized
    // start time. Otherwise they may start immediately.
    if (startedSynchronizedOnCompositor) {
        for (size_t i = 0; i < m_pending.size(); ++i) {
            if (!m_pending[i]->hasStartTime()) {
                m_waitingForCompositorAnimationStart.append(m_pending[i]);
            }
        }
    } else {
        for (size_t i = 0; i < m_pending.size(); ++i) {
            if (!m_pending[i]->hasStartTime()) {
                m_pending[i]->setStartTime(m_pending[i]->timeline()->currentTime());
                m_pending[i]->update(AnimationPlayer::UpdateOnDemand);
            }
        }
    }
    m_pending.clear();

    if (startedSynchronizedOnCompositor || m_waitingForCompositorAnimationStart.isEmpty())
        return !m_waitingForCompositorAnimationStart.isEmpty();

    // Check if we're still waiting for any compositor animations to start.
    for (size_t i = 0; i < m_waitingForCompositorAnimationStart.size(); ++i) {
        if (m_waitingForCompositorAnimationStart[i].get()->hasActiveAnimationsOnCompositor())
            return true;
    }

    // If not, go ahead and start any animations that were waiting.
    notifyCompositorAnimationStarted(monotonicallyIncreasingTime());
    return false;
}
void HTMLResourcePreloader::preload(PassOwnPtr<PreloadRequest> preload, const NetworkHintsInterface& networkHintsInterface)
{
    if (preload->isPreconnect()) {
        preconnectHost(preload.get(), networkHintsInterface);
        return;
    }
    // TODO(yoichio): Should preload if document is imported.
    if (!m_document->loader())
        return;
    FetchRequest request = preload->resourceRequest(m_document);
    // TODO(dgozman): This check should go to HTMLPreloadScanner, but this requires
    // making Document::completeURLWithOverride logic to be statically accessible.
    if (request.url().protocolIsData())
        return;
    if (preload->resourceType() == Resource::Script || preload->resourceType() == Resource::CSSStyleSheet || preload->resourceType() == Resource::ImportResource)
        request.setCharset(preload->charset().isEmpty() ? m_document->characterSet().string() : preload->charset());
    request.setForPreload(true);
    int duration = static_cast<int>(1000 * (monotonicallyIncreasingTime() - preload->discoveryTime()));
    DEFINE_STATIC_LOCAL(CustomCountHistogram, preloadDelayHistogram, ("WebCore.PreloadDelayMs", 0, 2000, 20));
    preloadDelayHistogram.count(duration);
    m_document->loader()->startPreload(preload->resourceType(), request);
}
Ejemplo n.º 3
0
LinkHighlight::LinkHighlight(Node* node, WebViewImpl* owningWebViewImpl)
    : m_node(node)
    , m_owningWebViewImpl(owningWebViewImpl)
    , m_currentGraphicsLayer(0)
    , m_usingNonCompositedContentHost(false)
    , m_geometryNeedsUpdate(false)
    , m_isAnimating(false)
    , m_startTime(monotonicallyIncreasingTime())
{
    ASSERT(m_node);
    ASSERT(owningWebViewImpl);
    WebCompositorSupport* compositorSupport = Platform::current()->compositorSupport();
    m_contentLayer = adoptPtr(compositorSupport->createContentLayer(this));
    m_clipLayer = adoptPtr(compositorSupport->createLayer());
    m_clipLayer->setAnchorPoint(WebFloatPoint());
    m_clipLayer->addChild(m_contentLayer->layer());
    m_contentLayer->layer()->setAnimationDelegate(this);
    m_contentLayer->layer()->setDrawsContent(true);
    m_contentLayer->layer()->setOpacity(1);
    m_geometryNeedsUpdate = true;
    updateGeometry();
}
Ejemplo n.º 4
0
void DocumentLoader::cancelLoadAfterXFrameOptionsOrCSPDenied(const ResourceResponse& response)
{
    InspectorInstrumentation::continueAfterXFrameOptionsDenied(m_frame, this, mainResourceIdentifier(), response, m_mainResource.get());

    setWasBlockedAfterXFrameOptionsOrCSP();

    // Pretend that this was an empty HTTP 200 response.  Don't reuse the
    // original URL for the empty page (https://crbug.com/622385).
    //
    // TODO(mkwst):  Remove this once XFO moves to the browser.
    // https://crbug.com/555418.
    clearMainResourceHandle();
    KURL blockedURL = SecurityOrigin::urlWithUniqueSecurityOrigin();
    m_originalRequest.setURL(blockedURL);
    m_request.setURL(blockedURL);
    m_redirectChain.removeLast();
    appendRedirect(blockedURL);
    m_response = ResourceResponse(blockedURL, "text/html", 0, nullAtom, String());
    finishedLoading(monotonicallyIncreasingTime());

    return;
}
Ejemplo n.º 5
0
HIDGamepad::HIDGamepad(IOHIDDeviceRef hidDevice, unsigned index)
    : PlatformGamepad(index)
    , m_hidDevice(hidDevice)
{
    m_connectTime = m_lastUpdateTime = monotonicallyIncreasingTime();

    CFNumberRef cfVendorID = (CFNumberRef)IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDVendorIDKey));
    CFNumberRef cfProductID = (CFNumberRef)IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDProductIDKey));

    int vendorID, productID;
    CFNumberGetValue(cfVendorID, kCFNumberIntType, &vendorID);
    CFNumberGetValue(cfProductID, kCFNumberIntType, &productID);

    CFStringRef cfProductName = (CFStringRef)IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDProductKey));
    String productName(cfProductName);

    // Currently the spec has no formatting for the id string.
    // This string formatting matches Firefox.
    m_id = String::format("%x-%x-%s", vendorID, productID, productName.utf8().data());

    initElements();
}
Ejemplo n.º 6
0
bool CCSingleThreadProxy::doComposite()
{
    ASSERT(!m_contextLost);
    {
      DebugScopedSetImplThread impl;
      double monotonicTime = monotonicallyIncreasingTime();
      double wallClockTime = currentTime();

      m_layerTreeHostImpl->animate(monotonicTime, wallClockTime);
      CCLayerTreeHostImpl::FrameData frame;
      m_layerTreeHostImpl->prepareToDraw(frame);
      m_layerTreeHostImpl->drawLayers(frame);
    }

    if (m_layerTreeHostImpl->isContextLost()) {
        m_contextLost = true;
        m_layerTreeHost->didLoseContext();
        return false;
    }

    return true;
}
Ejemplo n.º 7
0
void ResourceLoader::requestSynchronously(const ResourceRequest& request) {
  // downloadToFile is not supported for synchronous requests.
  DCHECK(!request.downloadToFile());
  DCHECK(m_loader);
  DCHECK_EQ(request.priority(), ResourceLoadPriorityHighest);

  WrappedResourceRequest requestIn(request);
  WebURLResponse responseOut;
  WebURLError errorOut;
  WebData dataOut;
  int64_t encodedDataLength = WebURLLoaderClient::kUnknownEncodedDataLength;
  int64_t encodedBodyLength = 0;
  m_loader->loadSynchronously(requestIn, responseOut, errorOut, dataOut,
                              encodedDataLength, encodedBodyLength);

  // A message dispatched while synchronously fetching the resource
  // can bring about the cancellation of this load.
  if (!m_loader)
    return;
  if (errorOut.reason) {
    didFail(errorOut, encodedDataLength, encodedBodyLength);
    return;
  }
  didReceiveResponse(responseOut);
  if (!m_loader)
    return;
  DCHECK_GE(responseOut.toResourceResponse().encodedBodyLength(), 0);

  // Follow the async case convention of not calling didReceiveData or
  // appending data to m_resource if the response body is empty. Copying the
  // empty buffer is a noop in most cases, but is destructive in the case of
  // a 304, where it will overwrite the cached data we should be reusing.
  if (dataOut.size()) {
    m_fetcher->didReceiveData(m_resource.get(), dataOut.data(), dataOut.size());
    m_resource->setResourceBuffer(dataOut);
  }
  didFinishLoading(monotonicallyIncreasingTime(), encodedDataLength,
                   encodedBodyLength);
}
Ejemplo n.º 8
0
void ThreadedCompositor::DisplayRefreshMonitor::displayRefreshCallback()
{
    bool shouldHandleDisplayRefreshNotification = false;
    {
        LockHolder locker(mutex());
        shouldHandleDisplayRefreshNotification = isScheduled() && isPreviousFrameDone();
        if (shouldHandleDisplayRefreshNotification) {
            setIsPreviousFrameDone(false);
            setMonotonicAnimationStartTime(monotonicallyIncreasingTime());
        }
    }

    if (shouldHandleDisplayRefreshNotification)
        DisplayRefreshMonitor::handleDisplayRefreshedNotificationOnMainThread(this);

    if (m_compositor) {
        if (m_compositor->m_clientRendersNextFrame.compareExchangeStrong(true, false))
            m_compositor->m_scene->renderNextFrame();
        if (m_compositor->m_coordinateUpdateCompletionWithClient.compareExchangeStrong(true, false))
            m_compositor->m_compositingRunLoop->updateCompleted();
    }
}
Ejemplo n.º 9
0
void CCThreadProxy::scheduledActionDrawAndSwap()
{
    TRACE_EVENT("CCThreadProxy::scheduledActionDrawAndSwap", this, 0);
    ASSERT(isImplThread());
    if (!m_layerTreeHostImpl)
        return;

    // FIXME: compute the frame display time more intelligently
    double monotonicTime = monotonicallyIncreasingTime();
    double wallClockTime = currentTime();

    m_inputHandlerOnImplThread->willDraw(monotonicTime);
    m_layerTreeHostImpl->animate(monotonicTime, wallClockTime);
    m_layerTreeHostImpl->drawLayers();

    // Check for a pending compositeAndReadback.
    if (m_readbackRequestOnImplThread) {
        m_layerTreeHostImpl->readback(m_readbackRequestOnImplThread->pixels, m_readbackRequestOnImplThread->rect);
        m_readbackRequestOnImplThread->success = !m_layerTreeHostImpl->isContextLost();
        m_readbackRequestOnImplThread->completion.signal();
        m_readbackRequestOnImplThread = 0;
    }

    m_layerTreeHostImpl->swapBuffers();

    // Process any finish request
    if (m_finishAllRenderingCompletionEventOnImplThread) {
        m_layerTreeHostImpl->finishAllRendering();
        m_finishAllRenderingCompletionEventOnImplThread->signal();
        m_finishAllRenderingCompletionEventOnImplThread = 0;
    }

    // Tell the main thread that the the newly-commited frame was drawn.
    if (m_nextFrameIsNewlyCommittedFrameOnImplThread) {
        m_nextFrameIsNewlyCommittedFrameOnImplThread = false;
        m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::didCommitAndDrawFrame));
    }
}
void ResourceLoader::requestSynchronously()
{
    OwnPtr<WebURLLoader> loader = adoptPtr(Platform::current()->createURLLoader());
    ASSERT(loader);

    // downloadToFile is not supported for synchronous requests.
    ASSERT(!m_request.downloadToFile());

    ResourcePtr<Resource> protectResource(m_resource);

    RELEASE_ASSERT(m_connectionState == ConnectionStateNew);
    m_connectionState = ConnectionStateStarted;

    WrappedResourceRequest requestIn(m_request);
    WebURLResponse responseOut;
    responseOut.initialize();
    WebURLError errorOut;
    WebData dataOut;
    loader->loadSynchronously(requestIn, responseOut, errorOut, dataOut);
    if (errorOut.reason) {
        if (m_state == Terminated) {
            // A message dispatched while synchronously fetching the resource
            // can bring about the cancellation of this load.
            ASSERT(!m_resource);
            return;
        }
        didFail(0, errorOut);
        return;
    }
    didReceiveResponse(0, responseOut);
    if (m_state == Terminated)
        return;
    RefPtr<ResourceLoadInfo> resourceLoadInfo = responseOut.toResourceResponse().resourceLoadInfo();
    int64_t encodedDataLength = resourceLoadInfo ? resourceLoadInfo->encodedDataLength : WebURLLoaderClient::kUnknownEncodedDataLength;
    m_fetcher->didReceiveData(m_resource, dataOut.data(), dataOut.size(), encodedDataLength);
    m_resource->setResourceBuffer(dataOut);
    didFinishLoading(0, monotonicallyIncreasingTime(), encodedDataLength);
}
Ejemplo n.º 11
0
void AnimationBase::freezeAtTime(double t)
{
    if (!m_compAnim)
        return;

    if (!m_startTime) {
        // If we haven't started yet, make it as if we started.
        LOG(Animations, "%p AnimationState %s -> StartWaitResponse", this, nameForState(m_animState));
        m_animState = AnimationStateStartWaitResponse;
        onAnimationStartResponse(monotonicallyIncreasingTime());
    }

    ASSERT(m_startTime);        // if m_startTime is zero, we haven't started yet, so we'll get a bad pause time.
    if (t <= m_animation->delay())
        m_pauseTime = m_startTime;
    else
        m_pauseTime = m_startTime + t - m_animation->delay();

#if USE(ACCELERATED_COMPOSITING)
    if (m_object && m_object->isComposited())
        toRenderBoxModelObject(m_object)->suspendAnimations(m_pauseTime);
#endif
}
Ejemplo n.º 12
0
MouseEvent* MouseEvent::create(const AtomicString& eventType,
                               AbstractView* view,
                               Event* underlyingEvent,
                               SimulatedClickCreationScope creationScope) {
  PlatformEvent::Modifiers modifiers = PlatformEvent::NoModifiers;
  if (UIEventWithKeyState* keyStateEvent =
          findEventWithKeyState(underlyingEvent)) {
    modifiers = keyStateEvent->modifiers();
  }

  PlatformMouseEvent::SyntheticEventType syntheticType =
      PlatformMouseEvent::Positionless;
  int screenX = 0;
  int screenY = 0;
  if (underlyingEvent && underlyingEvent->isMouseEvent()) {
    syntheticType = PlatformMouseEvent::RealOrIndistinguishable;
    MouseEvent* mouseEvent = toMouseEvent(underlyingEvent);
    screenX = mouseEvent->screenX();
    screenY = mouseEvent->screenY();
  }

  double timestamp = underlyingEvent ? underlyingEvent->platformTimeStamp()
                                     : monotonicallyIncreasingTime();
  MouseEvent* createdEvent = MouseEvent::create(
      eventType, true, true, view, 0, screenX, screenY, 0, 0, 0, 0, modifiers,
      0, 0, nullptr, timestamp, syntheticType, String(), nullptr);

  createdEvent->setTrusted(creationScope ==
                           SimulatedClickCreationScope::FromUserAgent);
  createdEvent->setUnderlyingEvent(underlyingEvent);
  if (syntheticType == PlatformMouseEvent::RealOrIndistinguishable) {
    MouseEvent* mouseEvent = toMouseEvent(createdEvent->underlyingEvent());
    createdEvent->initCoordinates(mouseEvent->clientX(), mouseEvent->clientY());
  }

  return createdEvent;
}
void SVGImageChromeClient::animationTimerFired(Timer<SVGImageChromeClient>*)
{
    if (!m_image)
        return;
    // serviceScriptedAnimations runs requestAnimationFrame callbacks, but SVG
    // images can't have any so we assert there's no script.
    ScriptForbiddenScope forbidScript;

    // As neither SVGImage nor this chrome client object are on the Oilpan heap,
    // this object's reference to the SVGImage will not be traced should a GC
    // strike below. Hence, we must ensure that they both remain alive for
    // duration of this call.
    //
    // This is cannot arise non-Oilpan as an ImageResource is an owned object
    // and will be promptly released along with its (SVG)Image..and everything
    // below, including this object and its timer. For code simplicity, the
    // object protection isn't made the conditional on Oilpan.
    //
    // FIXME: Oilpan: move this and other ChromeClients to the Oilpan heap
    // to render this protection redundant.
    RefPtr<SVGImage> protect(m_image);
    m_image->frameView()->page()->animator().serviceScriptedAnimations(monotonicallyIncreasingTime());
    m_image->frameView()->updateAllLifecyclePhases();
}
Ejemplo n.º 14
0
int JPEGImageEncoder::progressiveEncodeRowsJpegHelper(JPEGImageEncoderState* encoderState, unsigned char* data, int currentRowsCompleted, const double SlackBeforeDeadline, double deadlineSeconds)
{
    JPEGImageEncoderStateImpl* encoderStateImpl = static_cast<JPEGImageEncoderStateImpl*>(encoderState);
    Vector<JSAMPLE> row(encoderStateImpl->cinfo()->image_width * encoderStateImpl->cinfo()->input_components);
    SET_JUMP_BUFFER(encoderStateImpl->cinfo(), ProgressiveEncodeFailed);

    const size_t pixelRowStride = encoderStateImpl->cinfo()->image_width * 4;
    unsigned char* pixels = data + pixelRowStride * currentRowsCompleted;

    while (encoderStateImpl->cinfo()->next_scanline < encoderStateImpl->cinfo()->image_height) {
        JSAMPLE* rowData = row.data();
        RGBAtoRGB(pixels, encoderStateImpl->cinfo()->image_width, rowData);
        jpeg_write_scanlines(encoderStateImpl->cinfo(), &rowData, 1);
        pixels += pixelRowStride;
        currentRowsCompleted++;

        if (deadlineSeconds - SlackBeforeDeadline - monotonicallyIncreasingTime() <= 0) {
            return currentRowsCompleted;
        }
    }

    jpeg_finish_compress(encoderStateImpl->cinfo());
    return currentRowsCompleted;
}
Ejemplo n.º 15
0
bool CrossOriginPreflightResultCacheItem::parse(const ResourceResponse& response, String& errorDescription)
{
    m_methods.clear();
    if (!parseAccessControlAllowList(response.httpHeaderField("Access-Control-Allow-Methods"), m_methods)) {
        errorDescription = "Cannot parse Access-Control-Allow-Methods response header field.";
        return false;
    }

    m_headers.clear();
    if (!parseAccessControlAllowList(response.httpHeaderField("Access-Control-Allow-Headers"), m_headers)) {
        errorDescription = "Cannot parse Access-Control-Allow-Headers response header field.";
        return false;
    }

    unsigned expiryDelta;
    if (parseAccessControlMaxAge(response.httpHeaderField("Access-Control-Max-Age"), expiryDelta)) {
        if (expiryDelta > maxPreflightCacheTimeoutSeconds)
            expiryDelta = maxPreflightCacheTimeoutSeconds;
    } else
        expiryDelta = defaultPreflightCacheTimeoutSeconds;

    m_absoluteExpiryTime = monotonicallyIncreasingTime() + expiryDelta;
    return true;
}
void ValidationMessageClientImpl::checkAnchorStatus(Timer<ValidationMessageClientImpl>*)
{
    ASSERT(m_currentAnchor);
    if (monotonicallyIncreasingTime() >= m_finishTime || !currentView()) {
        hideValidationMessage(*m_currentAnchor);
        return;
    }

    // Check the visibility of the element.
    // FIXME: Can we check invisibility by scrollable non-frame elements?
    IntRect newAnchorRect = currentView()->contentsToRootView(m_currentAnchor->pixelSnappedBoundingBox());
    newAnchorRect = intersection(currentView()->convertToRootView(currentView()->boundsRect()), newAnchorRect);
    if (newAnchorRect.isEmpty()) {
        hideValidationMessage(*m_currentAnchor);
        return;
    }

    IntRect newAnchorRectInScreen = currentView()->hostWindow()->rootViewToScreen(newAnchorRect);
    if (newAnchorRectInScreen == m_lastAnchorRectInScreen && m_webView.pageScaleFactor() == m_lastPageScaleFactor)
        return;
    m_lastAnchorRectInScreen = newAnchorRectInScreen;
    m_lastPageScaleFactor = m_webView.pageScaleFactor();
    m_webView.client()->moveValidationMessage(newAnchorRect);
}
Ejemplo n.º 17
0
void SMILTimeContainer::setElapsed(SMILTime time)
{
    // If the documment didn't begin yet, record a new start time, we'll seek to once its possible.
    if (!m_beginTime) {
        m_presetStartTime = time.value();
        return;
    }

    if (m_beginTime)
        m_timer.stop();

    double now = monotonicallyIncreasingTime();
    m_beginTime = now - time.value();

    if (m_pauseTime) {
        m_resumeTime = m_pauseTime = now;
        m_accumulatedActiveTime = time.value();
    } else
        m_resumeTime = m_beginTime;

#ifndef NDEBUG
    m_preventScheduledAnimationsChanges = true;
#endif
    GroupedAnimationsMap::iterator end = m_scheduledAnimations.end();
    for (GroupedAnimationsMap::iterator it = m_scheduledAnimations.begin(); it != end; ++it) {
        AnimationsVector* scheduled = it->value.get();
        unsigned size = scheduled->size();
        for (unsigned n = 0; n < size; n++)
            scheduled->at(n)->reset();
    }
#ifndef NDEBUG
    m_preventScheduledAnimationsChanges = false;
#endif

    updateAnimations(time, true);
}
bool GraphicsLayerTextureMapper::addAnimation(const KeyframeValueList& valueList, const FloatSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset)
{
    ASSERT(!keyframesName.isEmpty());

    if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyWebkitTransform && valueList.property() != AnimatedPropertyOpacity))
        return false;

    bool listsMatch = false;
    bool hasBigRotation;

    if (valueList.property() == AnimatedPropertyWebkitTransform)
        listsMatch = validateTransformOperations(valueList, hasBigRotation) >= 0;

    const double currentTime = monotonicallyIncreasingTime();
    m_animations.add(TextureMapperAnimation(keyframesName, valueList, boxSize, anim, currentTime - timeOffset, listsMatch));
    // m_animationStartTime is the time of the first real frame of animation, now or delayed by a negative offset.
    if (timeOffset > 0)
        m_animationStartTime = currentTime;
    else
        m_animationStartTime = currentTime - timeOffset;
    notifyChange(AnimationChange);
    notifyChange(AnimationStarted);
    return true;
}
Ejemplo n.º 19
0
void LinkHighlight::startHighlightAnimationIfNeeded()
{
    if (m_isAnimating)
        return;

    m_isAnimating = true;
    const float startOpacity = 1;
    // FIXME: Should duration be configurable?
    const float fadeDuration = 0.1f;
    const float minPreFadeDuration = 0.1f;

    m_contentLayer->layer()->setOpacity(startOpacity);

    WebCompositorSupport* compositorSupport = Platform::current()->compositorSupport();

    OwnPtr<WebFloatAnimationCurve> curve = adoptPtr(compositorSupport->createFloatAnimationCurve());

    curve->add(WebFloatKeyframe(0, startOpacity));
    // Make sure we have displayed for at least minPreFadeDuration before starting to fade out.
    float extraDurationRequired = std::max(0.f, minPreFadeDuration - static_cast<float>(monotonicallyIncreasingTime() - m_startTime));
    if (extraDurationRequired)
        curve->add(WebFloatKeyframe(extraDurationRequired, startOpacity));
    // For layout tests we don't fade out.
    curve->add(WebFloatKeyframe(fadeDuration + extraDurationRequired, blink::layoutTestMode() ? startOpacity : 0));

    OwnPtr<WebAnimation> animation = adoptPtr(compositorSupport->createAnimation(*curve, WebAnimation::TargetPropertyOpacity));

    m_contentLayer->layer()->setDrawsContent(true);
    m_contentLayer->layer()->addAnimation(animation.leakPtr());

    invalidate();
    m_owningWebViewImpl->scheduleAnimation();
}
Ejemplo n.º 20
0
double AnimationControllerPrivate::beginAnimationUpdateTime()
{
    if (m_beginAnimationUpdateTime == cBeginAnimationUpdateTimeNotSet)
        m_beginAnimationUpdateTime = monotonicallyIncreasingTime();
    return m_beginAnimationUpdateTime;
}
Ejemplo n.º 21
0
void BitmapImage::startAnimation(bool catchUpIfNecessary)
{
    if (m_frameTimer || !shouldAnimate() || frameCount() <= 1)
        return;

    // If we aren't already animating, set now as the animation start time.
    const double time = monotonicallyIncreasingTime();
    if (!m_desiredFrameStartTime)
        m_desiredFrameStartTime = time;

    // Don't advance the animation to an incomplete frame.
    size_t nextFrame = (m_currentFrame + 1) % frameCount();
    if (!m_allDataReceived && !frameIsCompleteAtIndex(nextFrame))
        return;

    // Don't advance past the last frame if we haven't decoded the whole image
    // yet and our repetition count is potentially unset.  The repetition count
    // in a GIF can potentially come after all the rest of the image data, so
    // wait on it.
    if (!m_allDataReceived && repetitionCount(false) == cAnimationLoopOnce && m_currentFrame >= (frameCount() - 1))
        return;

    // Determine time for next frame to start.  By ignoring paint and timer lag
    // in this calculation, we make the animation appear to run at its desired
    // rate regardless of how fast it's being repainted.
    const double currentDuration = frameDurationAtIndex(m_currentFrame);
    m_desiredFrameStartTime += currentDuration;

    // When an animated image is more than five minutes out of date, the
    // user probably doesn't care about resyncing and we could burn a lot of
    // time looping through frames below.  Just reset the timings.
    const double cAnimationResyncCutoff = 5 * 60;
    if ((time - m_desiredFrameStartTime) > cAnimationResyncCutoff)
        m_desiredFrameStartTime = time + currentDuration;

    // The image may load more slowly than it's supposed to animate, so that by
    // the time we reach the end of the first repetition, we're well behind.
    // Clamp the desired frame start time in this case, so that we don't skip
    // frames (or whole iterations) trying to "catch up".  This is a tradeoff:
    // It guarantees users see the whole animation the second time through and
    // don't miss any repetitions, and is closer to what other browsers do; on
    // the other hand, it makes animations "less accurate" for pages that try to
    // sync an image and some other resource (e.g. audio), especially if users
    // switch tabs (and thus stop drawing the animation, which will pause it)
    // during that initial loop, then switch back later.
    if (nextFrame == 0 && m_repetitionsComplete == 0 && m_desiredFrameStartTime < time)
        m_desiredFrameStartTime = time;

    if (!catchUpIfNecessary || time < m_desiredFrameStartTime) {
        // Haven't yet reached time for next frame to start; delay until then.
        m_frameTimer = new Timer<BitmapImage>(this, &BitmapImage::advanceAnimation);
        m_frameTimer->startOneShot(std::max(m_desiredFrameStartTime - time, 0.));
    } else {
        // We've already reached or passed the time for the next frame to start.
        // See if we've also passed the time for frames after that to start, in
        // case we need to skip some frames entirely.  Remember not to advance
        // to an incomplete frame.
        for (size_t frameAfterNext = (nextFrame + 1) % frameCount(); frameIsCompleteAtIndex(frameAfterNext); frameAfterNext = (nextFrame + 1) % frameCount()) {
            // Should we skip the next frame?
            double frameAfterNextStartTime = m_desiredFrameStartTime + frameDurationAtIndex(nextFrame);
            if (time < frameAfterNextStartTime)
                break;

            // Yes; skip over it without notifying our observers.
            if (!internalAdvanceAnimation(true))
                return;
            m_desiredFrameStartTime = frameAfterNextStartTime;
            nextFrame = frameAfterNext;
        }

        // Draw the next frame immediately.  Note that m_desiredFrameStartTime
        // may be in the past, meaning the next time through this function we'll
        // kick off the next advancement sooner than this frame's duration would
        // suggest.
        if (internalAdvanceAnimation(false)) {
            // The image region has been marked dirty, but once we return to our
            // caller, draw() will clear it, and nothing will cause the
            // animation to advance again.  We need to start the timer for the
            // next frame running, or the animation can hang.  (Compare this
            // with when advanceAnimation() is called, and the region is dirtied
            // while draw() is not in the callstack, meaning draw() gets called
            // to update the region and thus startAnimation() is reached again.)
            // NOTE: For large images with slow or heavily-loaded systems,
            // throwing away data as we go (see destroyDecodedData()) means we
            // can spend so much time re-decoding data above that by the time we
            // reach here we're behind again.  If we let startAnimation() run
            // the catch-up code again, we can get long delays without painting
            // as we race the timer, or even infinite recursion.  In this
            // situation the best we can do is to simply change frames as fast
            // as possible, so force startAnimation() to set a zero-delay timer
            // and bail out if we're not caught up.
            startAnimation(false);
        }
    }
}
Ejemplo n.º 22
0
void SpeechSynthesis::fireEvent(const AtomicString& type, SpeechSynthesisUtterance* utterance, unsigned long charIndex, const String& name)
{
    utterance->dispatchEvent(SpeechSynthesisEvent::create(type, charIndex, (monotonicallyIncreasingTime() - utterance->startTime()), name));
}
Ejemplo n.º 23
0
void ProgressTracker::incrementProgress(unsigned long identifier, const char*, int length)
{
    ProgressItem* item = m_progressItems.get(identifier);
    
    // FIXME: Can this ever happen?
    if (!item)
        return;

    RefPtr<Frame> frame = m_originatingProgressFrame;
    
    frame->loader().client().willChangeEstimatedProgress();
    
    unsigned bytesReceived = length;
    double increment, percentOfRemainingBytes;
    long long remainingBytes, estimatedBytesForPendingRequests;
    
    item->bytesReceived += bytesReceived;
    if (item->bytesReceived > item->estimatedLength) {
        m_totalPageAndResourceBytesToLoad += ((item->bytesReceived * 2) - item->estimatedLength);
        item->estimatedLength = item->bytesReceived * 2;
    }
    
    int numPendingOrLoadingRequests = frame->loader().numPendingOrLoadingRequests(true);
    estimatedBytesForPendingRequests = progressItemDefaultEstimatedLength * numPendingOrLoadingRequests;
    remainingBytes = ((m_totalPageAndResourceBytesToLoad + estimatedBytesForPendingRequests) - m_totalBytesReceived);
    if (remainingBytes > 0)  // Prevent divide by 0.
        percentOfRemainingBytes = (double)bytesReceived / (double)remainingBytes;
    else
        percentOfRemainingBytes = 1.0;
    
    // For documents that use WebCore's layout system, treat first layout as the half-way point.
    // FIXME: The hasHTMLView function is a sort of roundabout way of asking "do you use WebCore's layout system".
    bool useClampedMaxProgress = frame->loader().client().hasHTMLView()
        && !frame->loader().stateMachine()->firstLayoutDone();
    double maxProgressValue = useClampedMaxProgress ? 0.5 : finalProgressValue;
    increment = (maxProgressValue - m_progressValue) * percentOfRemainingBytes;
    m_progressValue += increment;
    m_progressValue = min(m_progressValue, maxProgressValue);
    ASSERT(m_progressValue >= initialProgressValue);
    
    m_totalBytesReceived += bytesReceived;
    
    double now = monotonicallyIncreasingTime();
    double notifiedProgressTimeDelta = now - m_lastNotifiedProgressTime;
    
    LOG(Progress, "Progress incremented (%p) - value %f, tracked frames %d", this, m_progressValue, m_numProgressTrackedFrames);
    double notificationProgressDelta = m_progressValue - m_lastNotifiedProgressValue;
    if ((notificationProgressDelta >= m_progressNotificationInterval ||
         notifiedProgressTimeDelta >= m_progressNotificationTimeInterval) &&
        m_numProgressTrackedFrames > 0) {
        if (!m_finalProgressChangedSent) {
            if (m_progressValue == 1)
                m_finalProgressChangedSent = true;
            
            frame->loader().client().postProgressEstimateChangedNotification();

            m_lastNotifiedProgressValue = m_progressValue;
            m_lastNotifiedProgressTime = now;
        }
    }
    
    frame->loader().client().didChangeEstimatedProgress();
}
bool ScrollAnimationSmooth::updatePerAxisData(PerAxisData& data, ScrollGranularity granularity, float delta, float minScrollPosition, float maxScrollPosition)
{
    if (!data.startTime || !delta || (delta < 0) != (data.desiredPosition - data.currentPosition < 0)) {
        data.desiredPosition = data.currentPosition;
        data.startTime = 0;
    }
    float newPosition = data.desiredPosition + delta;

    newPosition = std::max(std::min(newPosition, maxScrollPosition), minScrollPosition);

    if (newPosition == data.desiredPosition)
        return false;

    double animationTime, repeatMinimumSustainTime, attackTime, releaseTime, maximumCoastTime;
    Curve coastTimeCurve;
    getAnimationParametersForGranularity(granularity, animationTime, repeatMinimumSustainTime, attackTime, releaseTime, coastTimeCurve, maximumCoastTime);

    data.desiredPosition = newPosition;
    if (!data.startTime)
        data.attackTime = attackTime;
    data.animationTime = animationTime;
    data.releaseTime = releaseTime;

    // Prioritize our way out of over constraint.
    if (data.attackTime + data.releaseTime > data.animationTime) {
        if (data.releaseTime > data.animationTime)
            data.releaseTime = data.animationTime;
        data.attackTime = data.animationTime - data.releaseTime;
    }

    if (!data.startTime) {
        // FIXME: This should be the time from the event that got us here.
        data.startTime = monotonicallyIncreasingTime() - tickTime / 2;
        data.startPosition = data.currentPosition;
        data.lastAnimationTime = data.startTime;
    }
    data.startVelocity = data.currentVelocity;

    double remainingDelta = data.desiredPosition - data.currentPosition;
    double attackAreaLeft = 0;
    double deltaTime = data.lastAnimationTime - data.startTime;
    double attackTimeLeft = std::max(0., data.attackTime - deltaTime);
    double timeLeft = data.animationTime - deltaTime;
    double minTimeLeft = data.releaseTime + std::min(repeatMinimumSustainTime, data.animationTime - data.releaseTime - attackTimeLeft);
    if (timeLeft < minTimeLeft) {
        data.animationTime = deltaTime + minTimeLeft;
        timeLeft = minTimeLeft;
    }

    if (maximumCoastTime > (repeatMinimumSustainTime + releaseTime)) {
        double targetMaxCoastVelocity = data.visibleLength * .25 * frameRate;
        // This needs to be as minimal as possible while not being intrusive to page up/down.
        double minCoastDelta = data.visibleLength;

        if (fabs(remainingDelta) > minCoastDelta) {
            double maxCoastDelta = maximumCoastTime * targetMaxCoastVelocity;
            double coastFactor = std::min(1., (fabs(remainingDelta) - minCoastDelta) / (maxCoastDelta - minCoastDelta));

            // We could play with the curve here - linear seems a little soft. Initial testing makes me want to feed into the sustain time more aggressively.
            double coastMinTimeLeft = std::min(maximumCoastTime, minTimeLeft + coastCurve(coastTimeCurve, coastFactor) * (maximumCoastTime - minTimeLeft));

            if (double additionalTime = std::max(0., coastMinTimeLeft - minTimeLeft)) {
                double additionalReleaseTime = std::min(additionalTime, releaseTime / (releaseTime + repeatMinimumSustainTime) * additionalTime);
                data.releaseTime = releaseTime + additionalReleaseTime;
                data.animationTime = deltaTime + coastMinTimeLeft;
                timeLeft = coastMinTimeLeft;
            }
        }
    }

    double releaseTimeLeft = std::min(timeLeft, data.releaseTime);
    double sustainTimeLeft = std::max(0., timeLeft - releaseTimeLeft - attackTimeLeft);
    if (attackTimeLeft) {
        double attackSpot = deltaTime / data.attackTime;
        attackAreaLeft = attackArea(Curve::Cubic, attackSpot, 1) * data.attackTime;
    }

    double releaseSpot = (data.releaseTime - releaseTimeLeft) / data.releaseTime;
    double releaseAreaLeft = releaseArea(Curve::Cubic, releaseSpot, 1) * data.releaseTime;

    data.desiredVelocity = remainingDelta / (attackAreaLeft + sustainTimeLeft + releaseAreaLeft);
    data.releasePosition = data.desiredPosition - data.desiredVelocity * releaseAreaLeft;
    if (attackAreaLeft)
        data.attackPosition = data.startPosition + data.desiredVelocity * attackAreaLeft;
    else
        data.attackPosition = data.releasePosition - (data.animationTime - data.releaseTime - data.attackTime) * data.desiredVelocity;

    if (sustainTimeLeft) {
        double roundOff = data.releasePosition - ((attackAreaLeft ? data.attackPosition : data.currentPosition) + data.desiredVelocity * sustainTimeLeft);
        data.desiredVelocity += roundOff / sustainTimeLeft;
    }

    return true;
}
Ejemplo n.º 25
0
void CCSingleThreadProxy::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration)
{
    m_layerTreeHostImpl->startPageScaleAnimation(targetPosition, useAnchor, scale, monotonicallyIncreasingTime(), duration);
}
Ejemplo n.º 26
0
void TimelineTimeConverter::reset()
{
    m_startOffset = monotonicallyIncreasingTime() - currentTime();
}
Ejemplo n.º 27
0
SharedWorkerGlobalScope::SharedWorkerGlobalScope(const String& name, const KURL& url, const String& userAgent, SharedWorkerThread* thread, PassOwnPtrWillBeRawPtr<WorkerClients> workerClients)
    : WorkerGlobalScope(url, userAgent, thread, monotonicallyIncreasingTime(), workerClients)
    , m_name(name)
{
    ScriptWrappable::init(this);
}
Ejemplo n.º 28
0
void MainResourceLoader::didReceiveData(const char* data, int length, long long encodedDataLength, bool allAtOnce)
{
    ASSERT(data);
    ASSERT(length != 0);

    ASSERT(!m_response.isNull());

#if USE(CFNETWORK) || PLATFORM(MAC)
    // Workaround for <rdar://problem/6060782>
    if (m_response.isNull()) {
        m_response = ResourceResponse(KURL(), "text/html", 0, String(), String());
        if (DocumentLoader* documentLoader = frameLoader()->activeDocumentLoader())
            documentLoader->setResponse(m_response);
    }
#endif

    // There is a bug in CFNetwork where callbacks can be dispatched even when loads are deferred.
    // See <rdar://problem/6304600> for more details.
#if !USE(CF)
    ASSERT(!defersLoading());
#endif

#if PLATFORM(MAC) && !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
    if (m_filter) {
        ASSERT(!wkFilterWasBlocked(m_filter));
        const char* blockedData = wkFilterAddData(m_filter, data, &length);
        // If we don't have blockedData, that means we're still accumulating data
        if (!blockedData) {
            // Transition to committed state.
            ResourceLoader::didReceiveData("", 0, 0, false);
            return;
        }

        data = blockedData;
        encodedDataLength = -1;
    }
#endif

    documentLoader()->applicationCacheHost()->mainResourceDataReceived(data, length, encodedDataLength, allAtOnce);

    // The additional processing can do anything including possibly removing the last
    // reference to this object; one example of this is 3266216.
    RefPtr<MainResourceLoader> protect(this);

    m_timeOfLastDataReceived = monotonicallyIncreasingTime();

    ResourceLoader::didReceiveData(data, length, encodedDataLength, allAtOnce);

#if PLATFORM(MAC) && !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
    if (WebFilterEvaluator *filter = m_filter) {
        // If we got here, it means we know if we were blocked or not. If we were blocked, we're
        // done loading the page altogether. Either way, we don't need the filter anymore.

        // Remove this->m_filter early so didFinishLoading doesn't see it.
        m_filter = 0;
        if (wkFilterWasBlocked(filter))
            cancel();
        wkFilterRelease(filter);
    }
#endif
}
Ejemplo n.º 29
0
void MainResourceLoader::didFinishLoading(double finishTime)
{
    // There is a bug in CFNetwork where callbacks can be dispatched even when loads are deferred.
    // See <rdar://problem/6304600> for more details.
#if !USE(CF)
    ASSERT(shouldLoadAsEmptyDocument(frameLoader()->activeDocumentLoader()->url()) || !defersLoading() || InspectorInstrumentation::isDebuggerPaused(m_frame.get()));
#endif

    // The additional processing can do anything including possibly removing the last
    // reference to this object.
    RefPtr<MainResourceLoader> protect(this);
    RefPtr<DocumentLoader> dl = documentLoader();

#if PLATFORM(MAC) && !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
    if (m_filter) {
        int length;
        const char* data = wkFilterDataComplete(m_filter, &length);
        WebFilterEvaluator *filter = m_filter;
        // Remove this->m_filter early so didReceiveData doesn't see it.
        m_filter = 0;
        if (data)
            didReceiveData(data, length, -1, false);
        wkFilterRelease(filter);
    }
#endif

    if (m_loadingMultipartContent)
        dl->maybeFinishLoadingMultipartContent();

    documentLoader()->timing()->setResponseEnd(finishTime ? finishTime : (m_timeOfLastDataReceived ? m_timeOfLastDataReceived : monotonicallyIncreasingTime()));
    documentLoader()->finishedLoading();
    ResourceLoader::didFinishLoading(finishTime);

    dl->applicationCacheHost()->finishedLoadingMainResource();
}
Ejemplo n.º 30
0
void DocumentThreadableLoader::start(const ResourceRequest& request) {
  // Setting an outgoing referer is only supported in the async code path.
  DCHECK(m_async || request.httpReferrer().isEmpty());

  m_sameOriginRequest =
      getSecurityOrigin()->canRequestNoSuborigin(request.url());
  m_requestContext = request.requestContext();
  m_redirectMode = request.fetchRedirectMode();

  if (!m_sameOriginRequest &&
      m_options.crossOriginRequestPolicy == DenyCrossOriginRequests) {
    InspectorInstrumentation::
        documentThreadableLoaderFailedToStartLoadingForClient(m_document,
                                                              m_client);
    ThreadableLoaderClient* client = m_client;
    clear();
    client->didFail(ResourceError(errorDomainBlinkInternal, 0,
                                  request.url().getString(),
                                  "Cross origin requests are not supported."));
    return;
  }

  m_requestStartedSeconds = monotonicallyIncreasingTime();

  // Save any headers on the request here. If this request redirects
  // cross-origin, we cancel the old request create a new one, and copy these
  // headers.
  m_requestHeaders = request.httpHeaderFields();

  // DocumentThreadableLoader is used by all javascript initiated fetch, so we
  // use this chance to record non-GET fetch script requests. However, this is
  // based on the following assumptions, so please be careful when adding
  // similar logic:
  // - ThreadableLoader is used as backend for all javascript initiated network
  //   fetches.
  // - Note that ThreadableLoader is also used for non-network fetch such as
  //   FileReaderLoader. However it emulates GET method so signal is not
  //   recorded here.
  // - ThreadableLoader w/ non-GET request is only created from javascript
  //   initiated fetch.
  // - Some non-script initiated fetches such as WorkerScriptLoader also use
  //   ThreadableLoader, but they are guaranteed to use GET method.
  if (request.httpMethod() != HTTPNames::GET) {
    if (Page* page = m_document->page())
      page->chromeClient().didObserveNonGetFetchFromScript();
  }

  ResourceRequest newRequest(request);
  if (m_requestContext != WebURLRequest::RequestContextFetch) {
    // When the request context is not "fetch", |crossOriginRequestPolicy|
    // represents the fetch request mode, and |credentialsRequested| represents
    // the fetch credentials mode. So we set those flags here so that we can see
    // the correct request mode and credentials mode in the service worker's
    // fetch event handler.
    switch (m_options.crossOriginRequestPolicy) {
      case DenyCrossOriginRequests:
        newRequest.setFetchRequestMode(
            WebURLRequest::FetchRequestModeSameOrigin);
        break;
      case UseAccessControl:
        if (m_options.preflightPolicy == ForcePreflight) {
          newRequest.setFetchRequestMode(
              WebURLRequest::FetchRequestModeCORSWithForcedPreflight);
        } else {
          newRequest.setFetchRequestMode(WebURLRequest::FetchRequestModeCORS);
        }
        break;
      case AllowCrossOriginRequests:
        SECURITY_CHECK(IsNoCORSAllowedContext(m_requestContext,
                                              request.skipServiceWorker()));
        newRequest.setFetchRequestMode(WebURLRequest::FetchRequestModeNoCORS);
        break;
    }
    if (m_resourceLoaderOptions.allowCredentials == AllowStoredCredentials) {
      newRequest.setFetchCredentialsMode(
          WebURLRequest::FetchCredentialsModeInclude);
    } else {
      newRequest.setFetchCredentialsMode(
          WebURLRequest::FetchCredentialsModeSameOrigin);
    }
  }

  // We assume that ServiceWorker is skipped for sync requests and unsupported
  // protocol requests by content/ code.
  if (m_async &&
      request.skipServiceWorker() == WebURLRequest::SkipServiceWorker::None &&
      SchemeRegistry::shouldTreatURLSchemeAsAllowingServiceWorkers(
          request.url().protocol()) &&
      m_document->fetcher()->isControlledByServiceWorker()) {
    if (newRequest.fetchRequestMode() == WebURLRequest::FetchRequestModeCORS ||
        newRequest.fetchRequestMode() ==
            WebURLRequest::FetchRequestModeCORSWithForcedPreflight) {
      m_fallbackRequestForServiceWorker = ResourceRequest(request);
      // m_fallbackRequestForServiceWorker is used when a regular controlling
      // service worker doesn't handle a cross origin request. When this happens
      // we still want to give foreign fetch a chance to handle the request, so
      // only skip the controlling service worker for the fallback request. This
      // is currently safe because of http://crbug.com/604084 the
      // wasFallbackRequiredByServiceWorker flag is never set when foreign fetch
      // handled a request.
      m_fallbackRequestForServiceWorker.setSkipServiceWorker(
          WebURLRequest::SkipServiceWorker::Controlling);
    }
    loadRequest(newRequest, m_resourceLoaderOptions);
    return;
  }

  dispatchInitialRequest(newRequest);
}