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/animation/AnimationPlayer.h" 33 34 #include "core/animation/Animation.h" 35 #include "core/animation/AnimationTimeline.h" 36 #include "core/dom/Document.h" 37 #include "core/events/AnimationPlayerEvent.h" 38 #include "core/frame/UseCounter.h" 39 #include "platform/TraceEvent.h" 40 #include "wtf/MathExtras.h" 41 42 namespace blink { 43 44 namespace { 45 46 static unsigned nextSequenceNumber() 47 { 48 static unsigned next = 0; 49 return ++next; 50 } 51 52 } 53 54 PassRefPtrWillBeRawPtr<AnimationPlayer> AnimationPlayer::create(ExecutionContext* executionContext, AnimationTimeline& timeline, AnimationNode* content) 55 { 56 RefPtrWillBeRawPtr<AnimationPlayer> player = adoptRefWillBeNoop(new AnimationPlayer(executionContext, timeline, content)); 57 player->uncancel(); 58 timeline.document()->compositorPendingAnimations().add(player.get()); 59 player->suspendIfNeeded(); 60 return player.release(); 61 } 62 63 AnimationPlayer::AnimationPlayer(ExecutionContext* executionContext, AnimationTimeline& timeline, AnimationNode* content) 64 : ActiveDOMObject(executionContext) 65 , m_playbackRate(1) 66 , m_startTime(nullValue()) 67 , m_holdTime(0) 68 , m_sequenceNumber(nextSequenceNumber()) 69 , m_content(content) 70 , m_timeline(&timeline) 71 , m_paused(false) 72 , m_held(true) 73 , m_isPausedForTesting(false) 74 , m_outdated(true) 75 , m_finished(true) 76 , m_compositorState(nullptr) 77 , m_compositorPending(true) 78 , m_currentTimePending(false) 79 , m_idle(true) 80 { 81 if (m_content) { 82 if (m_content->player()) { 83 m_content->player()->cancel(); 84 m_content->player()->setSource(0); 85 } 86 m_content->attach(this); 87 } 88 } 89 90 AnimationPlayer::~AnimationPlayer() 91 { 92 #if !ENABLE(OILPAN) 93 if (m_content) 94 m_content->detach(); 95 if (m_timeline) 96 m_timeline->playerDestroyed(this); 97 #endif 98 } 99 100 double AnimationPlayer::sourceEnd() const 101 { 102 return m_content ? m_content->endTimeInternal() : 0; 103 } 104 105 bool AnimationPlayer::limited(double currentTime) const 106 { 107 return (m_playbackRate < 0 && currentTime <= 0) || (m_playbackRate > 0 && currentTime >= sourceEnd()); 108 } 109 110 void AnimationPlayer::setCurrentTimeInternal(double newCurrentTime, TimingUpdateReason reason) 111 { 112 ASSERT(std::isfinite(newCurrentTime)); 113 114 bool oldHeld = m_held; 115 bool outdated = false; 116 bool isLimited = limited(newCurrentTime); 117 m_held = m_paused || !m_playbackRate || isLimited || std::isnan(m_startTime); 118 if (m_held) { 119 if (!oldHeld || m_holdTime != newCurrentTime) 120 outdated = true; 121 m_holdTime = newCurrentTime; 122 if (m_paused || !m_playbackRate) { 123 m_startTime = nullValue(); 124 } else if (isLimited && std::isnan(m_startTime) && reason == TimingUpdateForAnimationFrame) { 125 m_startTime = calculateStartTime(newCurrentTime); 126 } 127 } else { 128 m_holdTime = nullValue(); 129 m_startTime = calculateStartTime(newCurrentTime); 130 setFinished(false); 131 outdated = true; 132 } 133 134 if (outdated) { 135 setOutdated(); 136 } 137 } 138 139 // Update timing to reflect updated animation clock due to tick 140 void AnimationPlayer::updateCurrentTimingState(TimingUpdateReason reason) 141 { 142 if (m_held) { 143 setCurrentTimeInternal(m_holdTime, reason); 144 return; 145 } 146 if (!limited(calculateCurrentTime())) 147 return; 148 m_held = true; 149 m_holdTime = m_playbackRate < 0 ? 0 : sourceEnd(); 150 } 151 152 double AnimationPlayer::startTime(bool& isNull) const 153 { 154 double result = startTime(); 155 isNull = std::isnan(result); 156 return result; 157 } 158 159 double AnimationPlayer::startTime() const 160 { 161 UseCounter::count(executionContext(), UseCounter::AnimationPlayerGetStartTime); 162 return m_startTime * 1000; 163 } 164 165 double AnimationPlayer::currentTime(bool& isNull) 166 { 167 double result = currentTime(); 168 isNull = std::isnan(result); 169 return result; 170 } 171 172 double AnimationPlayer::currentTime() 173 { 174 UseCounter::count(executionContext(), UseCounter::AnimationPlayerGetCurrentTime); 175 if (m_currentTimePending || m_idle) 176 return std::numeric_limits<double>::quiet_NaN(); 177 return currentTimeInternal() * 1000; 178 } 179 180 double AnimationPlayer::currentTimeInternal() 181 { 182 updateCurrentTimingState(TimingUpdateOnDemand); 183 if (m_held) 184 return m_holdTime; 185 return calculateCurrentTime(); 186 } 187 188 void AnimationPlayer::preCommit(bool startOnCompositor) 189 { 190 if (m_compositorState && m_compositorState->pendingAction == Start) { 191 // Still waiting for a start time. 192 return; 193 } 194 195 bool softChange = m_compositorState && (paused() || m_compositorState->playbackRate != m_playbackRate); 196 bool hardChange = m_compositorState && (m_compositorState->sourceChanged || (m_compositorState->startTime != m_startTime && !std::isnan(m_compositorState->startTime) && !std::isnan(m_startTime))); 197 198 // FIXME: softChange && !hardChange should generate a Pause/ThenStart, 199 // not a Cancel, but we can't communicate these to the compositor yet. 200 201 bool changed = softChange || hardChange; 202 bool shouldCancel = (!playing() && m_compositorState) || changed; 203 bool shouldStart = playing() && (!m_compositorState || changed); 204 205 if (shouldCancel) { 206 cancelAnimationOnCompositor(); 207 m_compositorState = nullptr; 208 209 } 210 211 if (!shouldStart) { 212 m_currentTimePending = false; 213 } 214 215 if (shouldStart && startOnCompositor && maybeStartAnimationOnCompositor()) { 216 m_compositorState = adoptPtr(new CompositorState(*this)); 217 } 218 } 219 220 void AnimationPlayer::postCommit(double timelineTime) 221 { 222 m_compositorPending = false; 223 224 if (!m_compositorState || m_compositorState->pendingAction == None) 225 return; 226 227 switch (m_compositorState->pendingAction) { 228 case Start: 229 if (!std::isnan(m_compositorState->startTime)) { 230 ASSERT(m_startTime == m_compositorState->startTime); 231 m_compositorState->pendingAction = None; 232 } 233 break; 234 case Pause: 235 case PauseThenStart: 236 ASSERT(std::isnan(m_startTime)); 237 m_compositorState->pendingAction = None; 238 setCurrentTimeInternal((timelineTime - m_compositorState->startTime) * m_playbackRate, TimingUpdateForAnimationFrame); 239 m_currentTimePending = false; 240 break; 241 default: 242 ASSERT_NOT_REACHED(); 243 } 244 } 245 246 void AnimationPlayer::notifyCompositorStartTime(double timelineTime) 247 { 248 if (m_compositorState) { 249 ASSERT(m_compositorState->pendingAction == Start); 250 ASSERT(std::isnan(m_compositorState->startTime)); 251 252 double initialCompositorHoldTime = m_compositorState->holdTime; 253 m_compositorState->pendingAction = None; 254 m_compositorState->startTime = timelineTime + currentTimeInternal() / -m_playbackRate; 255 256 if (paused() || m_compositorState->playbackRate != m_playbackRate || m_compositorState->sourceChanged) { 257 // Paused state, playback rate, or source changed while starting. 258 setCompositorPending(); 259 } 260 261 if (m_startTime == timelineTime) { 262 // The start time was set to the incoming compositor start time. 263 // Unlikely, but possible. 264 // FIXME: Depending on what changed above this might still be pending. 265 // Maybe... 266 m_currentTimePending = false; 267 return; 268 } 269 270 if (!std::isnan(m_startTime) || currentTimeInternal() != initialCompositorHoldTime) { 271 // A new start time or current time was set while starting. 272 setCompositorPending(); 273 return; 274 } 275 } 276 277 if (playing()) { 278 ASSERT(std::isnan(m_startTime)); 279 ASSERT(m_held); 280 281 if (m_playbackRate == 0) { 282 setStartTimeInternal(timelineTime); 283 } else { 284 setStartTimeInternal(timelineTime + currentTimeInternal() / -m_playbackRate); 285 } 286 287 // FIXME: This avoids marking this player as outdated needlessly when a start time 288 // is notified, but we should refactor how outdating works to avoid this. 289 m_outdated = false; 290 291 m_currentTimePending = false; 292 } 293 } 294 295 double AnimationPlayer::calculateStartTime(double currentTime) const 296 { 297 return m_timeline->effectiveTime() - currentTime / m_playbackRate; 298 } 299 300 double AnimationPlayer::calculateCurrentTime() const 301 { 302 ASSERT(!m_held); 303 if (isNull(m_startTime) || !m_timeline) 304 return 0; 305 return (m_timeline->effectiveTime() - m_startTime) * m_playbackRate; 306 } 307 308 void AnimationPlayer::setCurrentTime(double newCurrentTime) 309 { 310 UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetCurrentTime); 311 if (!std::isfinite(newCurrentTime)) 312 return; 313 314 setCompositorPending(); 315 m_currentTimePending = false; 316 setCurrentTimeInternal(newCurrentTime / 1000, TimingUpdateOnDemand); 317 } 318 319 void AnimationPlayer::setStartTime(double startTime) 320 { 321 UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetStartTime); 322 if (m_paused || m_idle) 323 return; 324 if (!std::isfinite(startTime)) 325 return; 326 if (startTime == m_startTime) 327 return; 328 329 setCompositorPending(); 330 m_currentTimePending = false; 331 setStartTimeInternal(startTime / 1000); 332 } 333 334 void AnimationPlayer::setStartTimeInternal(double newStartTime) 335 { 336 ASSERT(!m_paused); 337 ASSERT(std::isfinite(newStartTime)); 338 ASSERT(newStartTime != m_startTime); 339 340 bool hadStartTime = hasStartTime(); 341 double previousCurrentTime = currentTimeInternal(); 342 m_startTime = newStartTime; 343 if (m_held && m_playbackRate) { 344 // If held, the start time would still be derrived from the hold time. 345 // Force a new, limited, current time. 346 m_held = false; 347 double currentTime = calculateCurrentTime(); 348 if (m_playbackRate > 0 && currentTime > sourceEnd()) { 349 currentTime = sourceEnd(); 350 } else if (m_playbackRate < 0 && currentTime < 0) { 351 currentTime = 0; 352 } 353 setCurrentTimeInternal(currentTime, TimingUpdateOnDemand); 354 } 355 double newCurrentTime = currentTimeInternal(); 356 357 if (previousCurrentTime != newCurrentTime) { 358 setOutdated(); 359 } else if (!hadStartTime && m_timeline) { 360 // Even though this player is not outdated, time to effect change is 361 // infinity until start time is set. 362 m_timeline->wake(); 363 } 364 } 365 366 void AnimationPlayer::setSource(AnimationNode* newSource) 367 { 368 if (m_content == newSource) 369 return; 370 371 setCompositorPending(true); 372 373 double storedCurrentTime = currentTimeInternal(); 374 if (m_content) 375 m_content->detach(); 376 m_content = newSource; 377 if (newSource) { 378 // FIXME: This logic needs to be updated once groups are implemented 379 if (newSource->player()) { 380 newSource->player()->cancel(); 381 newSource->player()->setSource(0); 382 } 383 newSource->attach(this); 384 setOutdated(); 385 } 386 setCurrentTimeInternal(storedCurrentTime, TimingUpdateOnDemand); 387 } 388 389 String AnimationPlayer::playState() 390 { 391 switch (playStateInternal()) { 392 case Idle: 393 return "idle"; 394 case Pending: 395 return "pending"; 396 case Running: 397 return "running"; 398 case Paused: 399 return "paused"; 400 case Finished: 401 return "finished"; 402 default: 403 ASSERT_NOT_REACHED(); 404 return ""; 405 } 406 } 407 408 AnimationPlayer::AnimationPlayState AnimationPlayer::playStateInternal() 409 { 410 if (m_idle) 411 return Idle; 412 if (m_currentTimePending || (isNull(m_startTime) && !m_paused && m_playbackRate != 0)) 413 return Pending; 414 if (m_paused) 415 return Paused; 416 if (finished()) 417 return Finished; 418 return Running; 419 } 420 421 void AnimationPlayer::pause() 422 { 423 if (m_paused) 424 return; 425 if (playing()) { 426 setCompositorPending(); 427 m_currentTimePending = true; 428 } 429 m_paused = true; 430 setCurrentTimeInternal(currentTimeInternal(), TimingUpdateOnDemand); 431 } 432 433 void AnimationPlayer::unpause() 434 { 435 if (!m_paused) 436 return; 437 setCompositorPending(); 438 m_currentTimePending = true; 439 unpauseInternal(); 440 } 441 442 void AnimationPlayer::unpauseInternal() 443 { 444 if (!m_paused) 445 return; 446 m_paused = false; 447 setCurrentTimeInternal(currentTimeInternal(), TimingUpdateOnDemand); 448 } 449 450 void AnimationPlayer::play() 451 { 452 if (!playing()) 453 m_startTime = nullValue(); 454 455 setCompositorPending(); 456 uncancel(); 457 unpauseInternal(); 458 if (!m_content) 459 return; 460 double currentTime = this->currentTimeInternal(); 461 if (m_playbackRate > 0 && (currentTime < 0 || currentTime >= sourceEnd())) 462 setCurrentTimeInternal(0, TimingUpdateOnDemand); 463 else if (m_playbackRate < 0 && (currentTime <= 0 || currentTime > sourceEnd())) 464 setCurrentTimeInternal(sourceEnd(), TimingUpdateOnDemand); 465 setFinished(false); 466 } 467 468 void AnimationPlayer::reverse() 469 { 470 if (!m_playbackRate) { 471 return; 472 } 473 474 uncancel(); 475 setPlaybackRateInternal(-m_playbackRate); 476 play(); 477 } 478 479 void AnimationPlayer::finish(ExceptionState& exceptionState) 480 { 481 if (!m_playbackRate || m_idle) { 482 return; 483 } 484 if (m_playbackRate > 0 && sourceEnd() == std::numeric_limits<double>::infinity()) { 485 exceptionState.throwDOMException(InvalidStateError, "AnimationPlayer has source content whose end time is infinity."); 486 return; 487 } 488 if (playing()) { 489 setCompositorPending(); 490 } 491 492 uncancel(); 493 494 double newCurrentTime = m_playbackRate < 0 ? 0 : sourceEnd(); 495 setCurrentTimeInternal(newCurrentTime, TimingUpdateOnDemand); 496 if (!paused()) { 497 m_startTime = calculateStartTime(newCurrentTime); 498 } 499 500 m_currentTimePending = false; 501 ASSERT(finished()); 502 } 503 504 const AtomicString& AnimationPlayer::interfaceName() const 505 { 506 return EventTargetNames::AnimationPlayer; 507 } 508 509 ExecutionContext* AnimationPlayer::executionContext() const 510 { 511 return ActiveDOMObject::executionContext(); 512 } 513 514 bool AnimationPlayer::hasPendingActivity() const 515 { 516 return m_pendingFinishedEvent || (!m_finished && hasEventListeners(EventTypeNames::finish)); 517 } 518 519 void AnimationPlayer::stop() 520 { 521 setFinished(true); 522 m_pendingFinishedEvent = nullptr; 523 } 524 525 bool AnimationPlayer::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event) 526 { 527 if (m_pendingFinishedEvent == event) 528 m_pendingFinishedEvent = nullptr; 529 return EventTargetWithInlineData::dispatchEvent(event); 530 } 531 532 double AnimationPlayer::playbackRate() const 533 { 534 UseCounter::count(executionContext(), UseCounter::AnimationPlayerGetPlaybackRate); 535 return m_playbackRate; 536 } 537 538 void AnimationPlayer::setPlaybackRate(double playbackRate) 539 { 540 UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetPlaybackRate); 541 if (!std::isfinite(playbackRate)) 542 return; 543 if (playbackRate == m_playbackRate) 544 return; 545 546 setPlaybackRateInternal(playbackRate); 547 } 548 549 void AnimationPlayer::setPlaybackRateInternal(double playbackRate) 550 { 551 ASSERT(std::isfinite(playbackRate)); 552 ASSERT(playbackRate != m_playbackRate); 553 554 setCompositorPending(); 555 if (!finished() && !paused() && hasStartTime()) 556 m_currentTimePending = true; 557 558 double storedCurrentTime = currentTimeInternal(); 559 if ((m_playbackRate < 0 && playbackRate >= 0) || (m_playbackRate > 0 && playbackRate <= 0)) 560 setFinished(false); 561 562 m_playbackRate = playbackRate; 563 m_startTime = std::numeric_limits<double>::quiet_NaN(); 564 setCurrentTimeInternal(storedCurrentTime, TimingUpdateOnDemand); 565 } 566 567 void AnimationPlayer::setOutdated() 568 { 569 m_outdated = true; 570 if (m_timeline) 571 m_timeline->setOutdatedAnimationPlayer(this); 572 } 573 574 bool AnimationPlayer::canStartAnimationOnCompositor() 575 { 576 if (m_playbackRate == 0 || (std::isinf(sourceEnd()) && m_playbackRate < 0)) 577 return false; 578 579 return m_timeline && m_content && m_content->isAnimation() && playing(); 580 } 581 582 bool AnimationPlayer::maybeStartAnimationOnCompositor() 583 { 584 if (!canStartAnimationOnCompositor()) 585 return false; 586 587 bool reversed = m_playbackRate < 0; 588 589 double startTime = timeline()->zeroTime() + startTimeInternal(); 590 if (reversed) { 591 startTime -= sourceEnd() / fabs(m_playbackRate); 592 } 593 594 double timeOffset = 0; 595 if (std::isnan(startTime)) { 596 timeOffset = reversed ? sourceEnd() - currentTimeInternal() : currentTimeInternal(); 597 timeOffset = timeOffset / fabs(m_playbackRate); 598 } 599 return toAnimation(m_content.get())->maybeStartAnimationOnCompositor(startTime, timeOffset, m_playbackRate); 600 } 601 602 void AnimationPlayer::setCompositorPending(bool sourceChanged) 603 { 604 // FIXME: Animation could notify this directly? 605 if (!hasActiveAnimationsOnCompositor()) { 606 m_compositorState.release(); 607 } 608 if (!m_compositorPending) { 609 m_compositorPending = true; 610 if (sourceChanged && m_compositorState) 611 m_compositorState->sourceChanged = true; 612 timeline()->document()->compositorPendingAnimations().add(this); 613 } 614 } 615 616 bool AnimationPlayer::hasActiveAnimationsOnCompositor() 617 { 618 if (!m_content || !m_content->isAnimation()) 619 return false; 620 621 return toAnimation(m_content.get())->hasActiveAnimationsOnCompositor(); 622 } 623 624 void AnimationPlayer::cancelAnimationOnCompositor() 625 { 626 if (hasActiveAnimationsOnCompositor()) 627 toAnimation(m_content.get())->cancelAnimationOnCompositor(); 628 } 629 630 bool AnimationPlayer::update(TimingUpdateReason reason) 631 { 632 if (!m_timeline) 633 return false; 634 635 updateCurrentTimingState(reason); 636 m_outdated = false; 637 638 if (m_content) { 639 double inheritedTime = m_idle || isNull(m_timeline->currentTimeInternal()) ? nullValue() : currentTimeInternal(); 640 // Special case for end-exclusivity when playing backwards. 641 if (inheritedTime == 0 && m_playbackRate < 0) 642 inheritedTime = -1; 643 m_content->updateInheritedTime(inheritedTime, reason); 644 } 645 646 if ((m_idle || finished()) && !m_finished) { 647 if (reason == TimingUpdateForAnimationFrame && (m_idle || hasStartTime())) { 648 const AtomicString& eventType = EventTypeNames::finish; 649 if (executionContext() && hasEventListeners(eventType)) { 650 double eventCurrentTime = currentTimeInternal() * 1000; 651 m_pendingFinishedEvent = AnimationPlayerEvent::create(eventType, eventCurrentTime, timeline()->currentTime()); 652 m_pendingFinishedEvent->setTarget(this); 653 m_pendingFinishedEvent->setCurrentTarget(this); 654 m_timeline->document()->enqueueAnimationFrameEvent(m_pendingFinishedEvent); 655 } 656 setFinished(true); 657 } 658 } 659 ASSERT(!m_outdated); 660 return !m_finished; 661 } 662 663 double AnimationPlayer::timeToEffectChange() 664 { 665 ASSERT(!m_outdated); 666 if (m_held || !hasStartTime()) 667 return std::numeric_limits<double>::infinity(); 668 if (!m_content) 669 return -currentTimeInternal() / m_playbackRate; 670 if (m_playbackRate > 0) 671 return m_content->timeToForwardsEffectChange() / m_playbackRate; 672 return m_content->timeToReverseEffectChange() / -m_playbackRate; 673 } 674 675 void AnimationPlayer::setFinished(bool finished) 676 { 677 if (m_finished && !finished) { 678 if (m_content) { 679 TRACE_EVENT_ASYNC_BEGIN1("blink", "Animation", this, "Name", TRACE_STR_COPY(m_content->name().utf8().data())); 680 } else { 681 TRACE_EVENT_ASYNC_BEGIN0("blink", "Animation", this); 682 } 683 } 684 if (!m_finished && finished) { 685 TRACE_EVENT_ASYNC_END0("blink", "Animation", this); 686 } 687 m_finished = finished; 688 } 689 690 void AnimationPlayer::cancel() 691 { 692 if (m_idle) 693 return; 694 695 m_holdTime = currentTimeInternal(); 696 m_held = true; 697 m_idle = true; 698 m_startTime = nullValue(); 699 m_currentTimePending = false; 700 setCompositorPending(); 701 } 702 703 void AnimationPlayer::uncancel() 704 { 705 if (!m_idle) 706 return; 707 708 m_idle = false; 709 m_held = true; 710 m_holdTime = 0; 711 setFinished(false); 712 } 713 714 715 #if !ENABLE(OILPAN) 716 bool AnimationPlayer::canFree() const 717 { 718 ASSERT(m_content); 719 return hasOneRef() && m_content->isAnimation() && m_content->hasOneRef(); 720 } 721 #endif 722 723 bool AnimationPlayer::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) 724 { 725 if (eventType == EventTypeNames::finish) 726 UseCounter::count(executionContext(), UseCounter::AnimationPlayerFinishEvent); 727 return EventTargetWithInlineData::addEventListener(eventType, listener, useCapture); 728 } 729 730 void AnimationPlayer::pauseForTesting(double pauseTime) 731 { 732 RELEASE_ASSERT(!paused()); 733 setCurrentTimeInternal(pauseTime, TimingUpdateOnDemand); 734 if (hasActiveAnimationsOnCompositor()) 735 toAnimation(m_content.get())->pauseAnimationForTestingOnCompositor(currentTimeInternal()); 736 m_isPausedForTesting = true; 737 pause(); 738 } 739 740 void AnimationPlayer::trace(Visitor* visitor) 741 { 742 visitor->trace(m_content); 743 visitor->trace(m_timeline); 744 visitor->trace(m_pendingFinishedEvent); 745 EventTargetWithInlineData::trace(visitor); 746 } 747 748 } // namespace 749