OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006 Eric Seidel <eric@webkit.org> | 2 * Copyright (C) 2006 Eric Seidel <eric@webkit.org> |
3 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. | 3 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. |
4 * Copyright (C) Research In Motion Limited 2011. All rights reserved. | 4 * Copyright (C) Research In Motion Limited 2011. All rights reserved. |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
8 * are met: | 8 * are met: |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 #include "platform/graphics/paint/ClipRecorder.h" | 58 #include "platform/graphics/paint/ClipRecorder.h" |
59 #include "platform/graphics/paint/CullRect.h" | 59 #include "platform/graphics/paint/CullRect.h" |
60 #include "platform/graphics/paint/DrawingRecorder.h" | 60 #include "platform/graphics/paint/DrawingRecorder.h" |
61 #include "platform/graphics/paint/PaintRecord.h" | 61 #include "platform/graphics/paint/PaintRecord.h" |
62 #include "platform/graphics/paint/PaintRecordBuilder.h" | 62 #include "platform/graphics/paint/PaintRecordBuilder.h" |
63 #include "platform/instrumentation/tracing/TraceEvent.h" | 63 #include "platform/instrumentation/tracing/TraceEvent.h" |
64 #include "platform/wtf/PassRefPtr.h" | 64 #include "platform/wtf/PassRefPtr.h" |
65 | 65 |
66 namespace blink { | 66 namespace blink { |
67 | 67 |
| 68 // SVGImageLocalFrameClient is used to wait until SVG document's load event |
| 69 // in the case where there are subresources asynchronously loaded. |
| 70 // |
| 71 // Reference cycle: SVGImage -(Persistent)-> Page -(Member)-> Frame -(Member)-> |
| 72 // FrameClient == SVGImageLocalFrameClient -(raw)-> SVGImage. |
| 73 class SVGImage::SVGImageLocalFrameClient : public EmptyLocalFrameClient { |
| 74 public: |
| 75 SVGImageLocalFrameClient(SVGImage* image) : image_(image) {} |
| 76 |
| 77 void ClearImage() { image_ = nullptr; } |
| 78 |
| 79 private: |
| 80 void DispatchDidHandleOnloadEvents() override { |
| 81 // The SVGImage was destructed before SVG load completion. |
| 82 if (!image_) |
| 83 return; |
| 84 |
| 85 image_->LoadCompleted(); |
| 86 } |
| 87 |
| 88 // Cleared manually by SVGImage's destructor when |image_| is destructed. |
| 89 SVGImage* image_; |
| 90 }; |
| 91 |
68 SVGImage::SVGImage(ImageObserver* observer) | 92 SVGImage::SVGImage(ImageObserver* observer) |
69 : Image(observer), | 93 : Image(observer), |
70 paint_controller_(PaintController::Create()), | 94 paint_controller_(PaintController::Create()), |
71 has_pending_timeline_rewind_(false) {} | 95 has_pending_timeline_rewind_(false) {} |
72 | 96 |
73 SVGImage::~SVGImage() { | 97 SVGImage::~SVGImage() { |
| 98 if (frame_client_) |
| 99 frame_client_->ClearImage(); |
| 100 |
74 if (page_) { | 101 if (page_) { |
75 // Store m_page in a local variable, clearing m_page, so that | 102 // Store m_page in a local variable, clearing m_page, so that |
76 // SVGImageChromeClient knows we're destructed. | 103 // SVGImageChromeClient knows we're destructed. |
77 Page* current_page = page_.Release(); | 104 Page* current_page = page_.Release(); |
78 // Break both the loader and view references to the frame | 105 // Break both the loader and view references to the frame |
79 current_page->WillBeDestroyed(); | 106 current_page->WillBeDestroyed(); |
80 } | 107 } |
81 | 108 |
82 // Verify that page teardown destroyed the Chrome | 109 // Verify that page teardown destroyed the Chrome |
83 DCHECK(!chrome_client_ || !chrome_client_->GetImage()); | 110 DCHECK(!chrome_client_ || !chrome_client_->GetImage()); |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 } | 625 } |
599 | 626 |
600 void SVGImage::UpdateUseCounters(const Document& document) const { | 627 void SVGImage::UpdateUseCounters(const Document& document) const { |
601 if (SVGSVGElement* root_element = SvgRootElement(page_.Get())) { | 628 if (SVGSVGElement* root_element = SvgRootElement(page_.Get())) { |
602 if (root_element->TimeContainer()->HasAnimations()) | 629 if (root_element->TimeContainer()->HasAnimations()) |
603 UseCounter::Count(document, | 630 UseCounter::Count(document, |
604 UseCounter::kSVGSMILAnimationInImageRegardlessOfCache); | 631 UseCounter::kSVGSMILAnimationInImageRegardlessOfCache); |
605 } | 632 } |
606 } | 633 } |
607 | 634 |
| 635 void SVGImage::LoadCompleted() { |
| 636 switch (load_state_) { |
| 637 case kInDataChanged: |
| 638 load_state_ = kLoadCompleted; |
| 639 break; |
| 640 |
| 641 case kWaitingForAsyncLoadCompletion: |
| 642 load_state_ = kLoadCompleted; |
| 643 if (GetImageObserver()) |
| 644 GetImageObserver()->AsyncLoadCompleted(this); |
| 645 break; |
| 646 |
| 647 case kDataChangedNotStarted: |
| 648 case kLoadCompleted: |
| 649 CHECK(false); |
| 650 break; |
| 651 } |
| 652 } |
| 653 |
608 Image::SizeAvailability SVGImage::DataChanged(bool all_data_received) { | 654 Image::SizeAvailability SVGImage::DataChanged(bool all_data_received) { |
609 TRACE_EVENT0("blink", "SVGImage::dataChanged"); | 655 TRACE_EVENT0("blink", "SVGImage::dataChanged"); |
610 | 656 |
611 // Don't do anything if is an empty image. | 657 // Don't do anything if is an empty image. |
612 if (!Data()->size()) | 658 if (!Data()->size()) |
613 return kSizeAvailable; | 659 return kSizeAvailable; |
614 | 660 |
615 if (all_data_received) { | 661 if (!all_data_received) |
616 // SVGImage will fire events (and the default C++ handlers run) but doesn't | 662 return page_ ? kSizeAvailable : kSizeUnavailable; |
617 // actually allow script to run so it's fine to call into it. We allow this | |
618 // since it means an SVG data url can synchronously load like other image | |
619 // types. | |
620 EventDispatchForbiddenScope::AllowUserAgentEvents allow_user_agent_events; | |
621 | 663 |
622 DEFINE_STATIC_LOCAL(LocalFrameClient, dummy_local_frame_client, | 664 CHECK(!page_); |
623 (EmptyLocalFrameClient::Create())); | |
624 | 665 |
625 CHECK(!page_); | 666 // SVGImage will fire events (and the default C++ handlers run) but doesn't |
| 667 // actually allow script to run so it's fine to call into it. We allow this |
| 668 // since it means an SVG data url can synchronously load like other image |
| 669 // types. |
| 670 EventDispatchForbiddenScope::AllowUserAgentEvents allow_user_agent_events; |
626 | 671 |
627 Page::PageClients page_clients; | 672 CHECK_EQ(load_state_, kDataChangedNotStarted); |
628 FillWithEmptyClients(page_clients); | 673 load_state_ = kInDataChanged; |
629 chrome_client_ = SVGImageChromeClient::Create(this); | |
630 page_clients.chrome_client = chrome_client_.Get(); | |
631 | 674 |
632 // FIXME: If this SVG ends up loading itself, we might leak the world. | 675 Page::PageClients page_clients; |
633 // The Cache code does not know about ImageResources holding Frames and | 676 FillWithEmptyClients(page_clients); |
634 // won't know to break the cycle. | 677 chrome_client_ = SVGImageChromeClient::Create(this); |
635 // This will become an issue when SVGImage will be able to load other | 678 page_clients.chrome_client = chrome_client_.Get(); |
636 // SVGImage objects, but we're safe now, because SVGImage can only be | |
637 // loaded by a top-level document. | |
638 Page* page; | |
639 { | |
640 TRACE_EVENT0("blink", "SVGImage::dataChanged::createPage"); | |
641 page = Page::Create(page_clients); | |
642 page->GetSettings().SetScriptEnabled(false); | |
643 page->GetSettings().SetPluginsEnabled(false); | |
644 page->GetSettings().SetAcceleratedCompositingEnabled(false); | |
645 | 679 |
646 // Because this page is detached, it can't get default font settings | 680 // FIXME: If this SVG ends up loading itself, we might leak the world. |
647 // from the embedder. Copy over font settings so we have sensible | 681 // The Cache code does not know about ImageResources holding Frames and |
648 // defaults. These settings are fixed and will not update if changed. | 682 // won't know to break the cycle. |
649 if (!Page::OrdinaryPages().IsEmpty()) { | 683 // This will become an issue when SVGImage will be able to load other |
650 Settings& default_settings = | 684 // SVGImage objects, but we're safe now, because SVGImage can only be |
651 (*Page::OrdinaryPages().begin())->GetSettings(); | 685 // loaded by a top-level document. |
652 page->GetSettings().GetGenericFontFamilySettings() = | 686 Page* page; |
653 default_settings.GetGenericFontFamilySettings(); | 687 { |
654 page->GetSettings().SetMinimumFontSize( | 688 TRACE_EVENT0("blink", "SVGImage::dataChanged::createPage"); |
655 default_settings.GetMinimumFontSize()); | 689 page = Page::Create(page_clients); |
656 page->GetSettings().SetMinimumLogicalFontSize( | 690 page->GetSettings().SetScriptEnabled(false); |
657 default_settings.GetMinimumLogicalFontSize()); | 691 page->GetSettings().SetPluginsEnabled(false); |
658 page->GetSettings().SetDefaultFontSize( | 692 page->GetSettings().SetAcceleratedCompositingEnabled(false); |
659 default_settings.GetDefaultFontSize()); | 693 |
660 page->GetSettings().SetDefaultFixedFontSize( | 694 // Because this page is detached, it can't get default font settings |
661 default_settings.GetDefaultFixedFontSize()); | 695 // from the embedder. Copy over font settings so we have sensible |
662 } | 696 // defaults. These settings are fixed and will not update if changed. |
| 697 if (!Page::OrdinaryPages().IsEmpty()) { |
| 698 Settings& default_settings = |
| 699 (*Page::OrdinaryPages().begin())->GetSettings(); |
| 700 page->GetSettings().GetGenericFontFamilySettings() = |
| 701 default_settings.GetGenericFontFamilySettings(); |
| 702 page->GetSettings().SetMinimumFontSize( |
| 703 default_settings.GetMinimumFontSize()); |
| 704 page->GetSettings().SetMinimumLogicalFontSize( |
| 705 default_settings.GetMinimumLogicalFontSize()); |
| 706 page->GetSettings().SetDefaultFontSize( |
| 707 default_settings.GetDefaultFontSize()); |
| 708 page->GetSettings().SetDefaultFixedFontSize( |
| 709 default_settings.GetDefaultFixedFontSize()); |
| 710 } |
663 } | 711 } |
664 | 712 |
665 LocalFrame* frame = nullptr; | 713 LocalFrame* frame = nullptr; |
666 { | 714 { |
667 TRACE_EVENT0("blink", "SVGImage::dataChanged::createFrame"); | 715 TRACE_EVENT0("blink", "SVGImage::dataChanged::createFrame"); |
668 frame = LocalFrame::Create(&dummy_local_frame_client, *page, 0); | 716 DCHECK(!frame_client_); |
| 717 frame_client_ = new SVGImageLocalFrameClient(this); |
| 718 frame = LocalFrame::Create(frame_client_, *page, 0); |
669 frame->SetView(FrameView::Create(*frame)); | 719 frame->SetView(FrameView::Create(*frame)); |
670 frame->Init(); | 720 frame->Init(); |
671 } | 721 } |
672 | 722 |
673 FrameLoader& loader = frame->Loader(); | 723 FrameLoader& loader = frame->Loader(); |
674 loader.ForceSandboxFlags(kSandboxAll); | 724 loader.ForceSandboxFlags(kSandboxAll); |
675 | 725 |
676 frame->View()->SetScrollbarsSuppressed(true); | 726 frame->View()->SetScrollbarsSuppressed(true); |
677 // SVG Images will always synthesize a viewBox, if it's not available, and | 727 // SVG Images will always synthesize a viewBox, if it's not available, and |
678 // thus never see scrollbars. | 728 // thus never see scrollbars. |
679 frame->View()->SetCanHaveScrollbars(false); | 729 frame->View()->SetCanHaveScrollbars(false); |
680 // SVG Images are transparent. | 730 // SVG Images are transparent. |
681 frame->View()->SetBaseBackgroundColor(Color::kTransparent); | 731 frame->View()->SetBaseBackgroundColor(Color::kTransparent); |
682 | 732 |
683 page_ = page; | 733 page_ = page; |
684 | 734 |
685 TRACE_EVENT0("blink", "SVGImage::dataChanged::load"); | 735 TRACE_EVENT0("blink", "SVGImage::dataChanged::load"); |
686 loader.Load(FrameLoadRequest( | 736 loader.Load(FrameLoadRequest( |
687 0, ResourceRequest(BlankURL()), | 737 0, ResourceRequest(BlankURL()), |
688 SubstituteData(Data(), AtomicString("image/svg+xml"), | 738 SubstituteData(Data(), AtomicString("image/svg+xml"), |
689 AtomicString("UTF-8"), KURL(), kForceSynchronousLoad))); | 739 AtomicString("UTF-8"), KURL(), kForceSynchronousLoad))); |
690 | 740 |
691 // Set the concrete object size before a container size is available. | 741 // Set the concrete object size before a container size is available. |
692 intrinsic_size_ = RoundedIntSize(ConcreteObjectSize(FloatSize( | 742 intrinsic_size_ = RoundedIntSize(ConcreteObjectSize(FloatSize( |
693 LayoutReplaced::kDefaultWidth, LayoutReplaced::kDefaultHeight))); | 743 LayoutReplaced::kDefaultWidth, LayoutReplaced::kDefaultHeight))); |
| 744 |
| 745 DCHECK(page_); |
| 746 switch (load_state_) { |
| 747 case kInDataChanged: |
| 748 load_state_ = kWaitingForAsyncLoadCompletion; |
| 749 return kSizeAvailableAndLoadingAsynchronously; |
| 750 |
| 751 case kLoadCompleted: |
| 752 return kSizeAvailable; |
| 753 |
| 754 case kDataChangedNotStarted: |
| 755 case kWaitingForAsyncLoadCompletion: |
| 756 CHECK(false); |
| 757 break; |
694 } | 758 } |
695 | 759 |
696 return page_ ? kSizeAvailable : kSizeUnavailable; | 760 NOTREACHED(); |
| 761 return kSizeAvailable; |
697 } | 762 } |
698 | 763 |
699 String SVGImage::FilenameExtension() const { | 764 String SVGImage::FilenameExtension() const { |
700 return "svg"; | 765 return "svg"; |
701 } | 766 } |
702 | 767 |
703 } // namespace blink | 768 } // namespace blink |
OLD | NEW |