The Page's muted setting should not affect the HTMLMediaElement's 'muted' IDL attribute.
authoradachan@apple.com <adachan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 30 Oct 2014 22:06:12 +0000 (22:06 +0000)
committeradachan@apple.com <adachan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 30 Oct 2014 22:06:12 +0000 (22:06 +0000)
https://bugs.webkit.org/show_bug.cgi?id=138215

Reviewed by Eric Carlson.

Source/WebCore:

Add m_muted in Page to keep track of the Page's muted state. Change AudioProducer::setMuted()
to pageMutedStateDidChange(). When that method is called, the AudioProducer is supposed to
update its muted state again taking the Page's muted state into account.

Add HTMLMediaElement::effectiveMuted(), which returns the effective muted state of the
HTMLMediaElement, taking the Page's muted state into account.

Test: media/video-muted-after-setting-page-muted-state.html

* dom/Document.cpp:
(WebCore::Document::pageMutedStateDidChange):
(WebCore::Document::setMuted): Deleted.
* dom/Document.h:
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::setMuted):
Set the MediaPlayer's muted state to the result of effectiveMuted() rather than m_muted.
(WebCore::HTMLMediaElement::updateVolume):
Ditto, and also make sure the MediaController's muted state does not override the Page's
muted state.
(WebCore::HTMLMediaElement::updatePlayState):
Set the MediaPlayer's muted state to the result of effectiveMuted() rather than muted().
(WebCore::HTMLMediaElement::pageMutedStateDidChange):
Call updateVolume(), which will update the MediaPlayer's muted state.
(WebCore::HTMLMediaElement::effectiveMuted):
Figure out the muted value taking Page's muted state into account.
* html/HTMLMediaElement.h:
* page/AudioProducer.h:
* page/Page.cpp:
(WebCore::Page::Page):
(WebCore::Page::setMuted):
Update m_muted, and only iterate through the frames' documents to call pageMutedStateDidChange()
if m_muted changes.
* page/Page.h:
(WebCore::Page::isMuted):
* testing/Internals.cpp:
(WebCore::Internals::setPageMuted):
Expose a way to set the Page's muted state in Internals for testing.
* testing/Internals.h:
* testing/Internals.idl:

LayoutTests:

* media/video-muted-after-setting-page-muted-state-expected.txt: Added.
* media/video-muted-after-setting-page-muted-state.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@175384 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
LayoutTests/ChangeLog
LayoutTests/media/video-muted-after-setting-page-muted-state-expected.txt [new file with mode: 0644]
LayoutTests/media/video-muted-after-setting-page-muted-state.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/HTMLMediaElement.h
Source/WebCore/page/AudioProducer.h
Source/WebCore/page/Page.cpp
Source/WebCore/page/Page.h
Source/WebCore/testing/Internals.cpp
Source/WebCore/testing/Internals.h
Source/WebCore/testing/Internals.idl

index 55bec45..2ed5625 100644 (file)
@@ -1,3 +1,13 @@
+2014-10-30  Ada Chan  <adachan@apple.com>
+
+        The Page's muted setting should not affect the HTMLMediaElement's 'muted' IDL attribute.
+        https://bugs.webkit.org/show_bug.cgi?id=138215
+
+        Reviewed by Eric Carlson.
+
+        * media/video-muted-after-setting-page-muted-state-expected.txt: Added.
+        * media/video-muted-after-setting-page-muted-state.html: Added.
+
 2014-10-30  Brady Eidson  <beidson@apple.com>
 
         IndexedDB is deleting data when a PK is shared amongst two objectStores
 2014-10-30  Brady Eidson  <beidson@apple.com>
 
         IndexedDB is deleting data when a PK is shared amongst two objectStores
diff --git a/LayoutTests/media/video-muted-after-setting-page-muted-state-expected.txt b/LayoutTests/media/video-muted-after-setting-page-muted-state-expected.txt
new file mode 100644 (file)
index 0000000..f7a4b3b
--- /dev/null
@@ -0,0 +1,10 @@
+
+Test 'muted' IDL attribute after setting the Page's muted state. The Page's muted state should not affect the 'muted' IDL attribute.
+
+EXPECTED (video.muted == 'false') OK
+EXPECTED (video.muted == 'false') OK
+RUN(video.muted = true)
+EXPECTED (video.muted == 'true') OK
+EXPECTED (video.muted == 'true') OK
+END OF TEST
+
diff --git a/LayoutTests/media/video-muted-after-setting-page-muted-state.html b/LayoutTests/media/video-muted-after-setting-page-muted-state.html
new file mode 100644 (file)
index 0000000..e50d13f
--- /dev/null
@@ -0,0 +1,17 @@
+<video controls></video>
+<p>Test 'muted' IDL attribute after setting the Page's muted state. The Page's muted state should not affect the 'muted' IDL attribute.<p>
+<script src=media-file.js></script>
+<script src=video-test.js></script>
+<script>
+    testExpected("video.muted", false);
+    if (window.internals)
+        internals.setPageMuted(true);
+    testExpected("video.muted", false);
+
+    run("video.muted = true");
+    testExpected("video.muted", true);
+    if (window.internals)
+        internals.setPageMuted(false);
+    testExpected("video.muted", true);
+    endTest();
+</script>
index fb84a98..7f81769 100644 (file)
@@ -1,3 +1,50 @@
+2014-10-30  Ada Chan  <adachan@apple.com>
+
+        The Page's muted setting should not affect the HTMLMediaElement's 'muted' IDL attribute.
+        https://bugs.webkit.org/show_bug.cgi?id=138215
+
+        Reviewed by Eric Carlson.
+
+        Add m_muted in Page to keep track of the Page's muted state. Change AudioProducer::setMuted()
+        to pageMutedStateDidChange(). When that method is called, the AudioProducer is supposed to
+        update its muted state again taking the Page's muted state into account.
+
+        Add HTMLMediaElement::effectiveMuted(), which returns the effective muted state of the
+        HTMLMediaElement, taking the Page's muted state into account.
+
+        Test: media/video-muted-after-setting-page-muted-state.html
+
+        * dom/Document.cpp:
+        (WebCore::Document::pageMutedStateDidChange):
+        (WebCore::Document::setMuted): Deleted.
+        * dom/Document.h:
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::setMuted):
+        Set the MediaPlayer's muted state to the result of effectiveMuted() rather than m_muted.
+        (WebCore::HTMLMediaElement::updateVolume):
+        Ditto, and also make sure the MediaController's muted state does not override the Page's
+        muted state.
+        (WebCore::HTMLMediaElement::updatePlayState):
+        Set the MediaPlayer's muted state to the result of effectiveMuted() rather than muted().
+        (WebCore::HTMLMediaElement::pageMutedStateDidChange):
+        Call updateVolume(), which will update the MediaPlayer's muted state.
+        (WebCore::HTMLMediaElement::effectiveMuted):
+        Figure out the muted value taking Page's muted state into account.
+        * html/HTMLMediaElement.h:
+        * page/AudioProducer.h:
+        * page/Page.cpp:
+        (WebCore::Page::Page):
+        (WebCore::Page::setMuted):
+        Update m_muted, and only iterate through the frames' documents to call pageMutedStateDidChange()
+        if m_muted changes.
+        * page/Page.h:
+        (WebCore::Page::isMuted):
+        * testing/Internals.cpp:
+        (WebCore::Internals::setPageMuted):
+        Expose a way to set the Page's muted state in Internals for testing.
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
 2014-10-30  Myles C. Maxfield  <mmaxfield@apple.com>
 
         Use references in calculateMinimumPageHeight() for non-optional arguments
 2014-10-30  Myles C. Maxfield  <mmaxfield@apple.com>
 
         Use references in calculateMinimumPageHeight() for non-optional arguments
index aea1edb..ffa0266 100644 (file)
@@ -3304,10 +3304,10 @@ void Document::updateIsPlayingAudio()
         page()->updateIsPlayingAudio();
 }
 
         page()->updateIsPlayingAudio();
 }
 
-void Document::setMuted(bool muted)
+void Document::pageMutedStateDidChange()
 {
     for (auto audioProducer : m_audioProducers)
 {
     for (auto audioProducer : m_audioProducers)
-        audioProducer->setMuted(muted);
+        audioProducer->pageMutedStateDidChange();
 }
 
 void Document::styleResolverChanged(StyleResolverUpdateFlag updateFlag)
 }
 
 void Document::styleResolverChanged(StyleResolverUpdateFlag updateFlag)
index 4273bda..c00e544 100644 (file)
@@ -1292,7 +1292,7 @@ public:
     void removeAudioProducer(AudioProducer*);
     bool isPlayingAudio() const { return m_isPlayingAudio; }
     void updateIsPlayingAudio();
     void removeAudioProducer(AudioProducer*);
     bool isPlayingAudio() const { return m_isPlayingAudio; }
     void updateIsPlayingAudio();
-    void setMuted(bool);
+    void pageMutedStateDidChange();
 
 protected:
     enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 };
 
 protected:
     enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 };
index 13b3150..389a3d4 100644 (file)
@@ -3001,7 +3001,7 @@ void HTMLMediaElement::setMuted(bool muted)
         // Avoid recursion when the player reports volume changes.
         if (!processingMediaPlayerCallback()) {
             if (m_player) {
         // Avoid recursion when the player reports volume changes.
         if (!processingMediaPlayerCallback()) {
             if (m_player) {
-                m_player->setMuted(m_muted);
+                m_player->setMuted(effectiveMuted());
                 if (hasMediaControls())
                     mediaControls()->changedMute();
             }
                 if (hasMediaControls())
                     mediaControls()->changedMute();
             }
@@ -4470,11 +4470,11 @@ void HTMLMediaElement::updateVolume()
     if (!processingMediaPlayerCallback()) {
         Page* page = document().page();
         double volumeMultiplier = page ? page->mediaVolume() : 1;
     if (!processingMediaPlayerCallback()) {
         Page* page = document().page();
         double volumeMultiplier = page ? page->mediaVolume() : 1;
-        bool shouldMute = muted();
+        bool shouldMute = effectiveMuted();
 
         if (m_mediaController) {
             volumeMultiplier *= m_mediaController->volume();
 
         if (m_mediaController) {
             volumeMultiplier *= m_mediaController->volume();
-            shouldMute = m_mediaController->muted();
+            shouldMute = m_mediaController->muted() || (page && page->isMuted());
         }
 
         m_player->setMuted(shouldMute);
         }
 
         m_player->setMuted(shouldMute);
@@ -4520,7 +4520,7 @@ void HTMLMediaElement::updatePlayState()
             // Set rate, muted before calling play in case they were set before the media engine was setup.
             // The media engine should just stash the rate and muted values since it isn't already playing.
             m_player->setRate(effectivePlaybackRate());
             // Set rate, muted before calling play in case they were set before the media engine was setup.
             // The media engine should just stash the rate and muted values since it isn't already playing.
             m_player->setRate(effectivePlaybackRate());
-            m_player->setMuted(muted());
+            m_player->setMuted(effectiveMuted());
 
             m_player->play();
         }
 
             m_player->play();
         }
@@ -6032,6 +6032,16 @@ bool HTMLMediaElement::isPlayingAudio()
     return isPlaying() && hasAudio();
 }
 
     return isPlaying() && hasAudio();
 }
 
+void HTMLMediaElement::pageMutedStateDidChange()
+{
+    updateVolume();
+}
+
+bool HTMLMediaElement::effectiveMuted() const
+{
+    return muted() || (document().page() && document().page()->isMuted());
+}
+
 bool HTMLMediaElement::doesHaveAttribute(const AtomicString& attribute, AtomicString* value) const
 {
     QualifiedName attributeName(nullAtom, attribute, nullAtom);
 bool HTMLMediaElement::doesHaveAttribute(const AtomicString& attribute, AtomicString* value) const
 {
     QualifiedName attributeName(nullAtom, attribute, nullAtom);
index e8f3dcc..4637374 100644 (file)
@@ -712,6 +712,9 @@ private:
 
     // AudioProducer overrides
     virtual bool isPlayingAudio() override;
 
     // AudioProducer overrides
     virtual bool isPlayingAudio() override;
+    virtual void pageMutedStateDidChange() override;
+
+    bool effectiveMuted() const;
 
     void registerWithDocument(Document&);
     void unregisterWithDocument(Document&);
 
     void registerWithDocument(Document&);
     void unregisterWithDocument(Document&);
index e0212bc..e14750b 100644 (file)
@@ -31,7 +31,7 @@ namespace WebCore {
 class AudioProducer {
 public:
     virtual bool isPlayingAudio() = 0;
 class AudioProducer {
 public:
     virtual bool isPlayingAudio() = 0;
-    virtual void setMuted(bool) = 0;
+    virtual void pageMutedStateDidChange() = 0;
 
 protected:
     virtual ~AudioProducer() { }
 
 protected:
     virtual ~AudioProducer() { }
index 8a2a028..19737a5 100644 (file)
@@ -160,6 +160,7 @@ Page::Page(PageClients& pageClients)
     , m_inLowQualityInterpolationMode(false)
     , m_areMemoryCacheClientCallsEnabled(true)
     , m_mediaVolume(1)
     , m_inLowQualityInterpolationMode(false)
     , m_areMemoryCacheClientCallsEnabled(true)
     , m_mediaVolume(1)
+    , m_muted(false)
     , m_pageScaleFactor(1)
     , m_zoomedOutPageScaleFactor(0)
     , m_deviceScaleFactor(1)
     , m_pageScaleFactor(1)
     , m_zoomedOutPageScaleFactor(0)
     , m_deviceScaleFactor(1)
@@ -1215,8 +1216,13 @@ void Page::updateIsPlayingAudio()
 
 void Page::setMuted(bool muted)
 {
 
 void Page::setMuted(bool muted)
 {
+    if (m_muted == muted)
+        return;
+
+    m_muted = muted;
+
     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
     for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
-        frame->document()->setMuted(muted);
+        frame->document()->pageMutedStateDidChange();
 }
 
 #if !ASSERT_DISABLED
 }
 
 #if !ASSERT_DISABLED
index 7345504..af7f8ac 100644 (file)
@@ -438,6 +438,7 @@ public:
 
     bool isPlayingAudio() const { return m_isPlayingAudio; }
     void updateIsPlayingAudio();
 
     bool isPlayingAudio() const { return m_isPlayingAudio; }
     void updateIsPlayingAudio();
+    bool isMuted() const { return m_muted; }
     WEBCORE_EXPORT void setMuted(bool);
 
 private:
     WEBCORE_EXPORT void setMuted(bool);
 
 private:
@@ -517,6 +518,7 @@ private:
     bool m_inLowQualityInterpolationMode;
     bool m_areMemoryCacheClientCallsEnabled;
     float m_mediaVolume;
     bool m_inLowQualityInterpolationMode;
     bool m_areMemoryCacheClientCallsEnabled;
     float m_mediaVolume;
+    bool m_muted;
 
     float m_pageScaleFactor;
     float m_zoomedOutPageScaleFactor;
 
     float m_pageScaleFactor;
     float m_zoomedOutPageScaleFactor;
index fc36d8f..2b22c48 100644 (file)
@@ -2402,4 +2402,14 @@ String Internals::pageOverlayLayerTreeAsText(ExceptionCode& ec) const
     return MockPageOverlayClient::shared().layerTreeAsText(document->frame()->mainFrame());
 }
 
     return MockPageOverlayClient::shared().layerTreeAsText(document->frame()->mainFrame());
 }
 
+void Internals::setPageMuted(bool muted)
+{
+    Document* document = contextDocument();
+    if (!document)
+        return;
+
+    if (Page* page = document->page())
+        page->setMuted(muted);
+}
+
 }
 }
index 3c74910..f4f806b 100644 (file)
@@ -346,6 +346,8 @@ public:
     void installMockPageOverlay(const String& overlayType, ExceptionCode&);
     String pageOverlayLayerTreeAsText(ExceptionCode&) const;
 
     void installMockPageOverlay(const String& overlayType, ExceptionCode&);
     String pageOverlayLayerTreeAsText(ExceptionCode&) const;
 
+    void setPageMuted(bool);
+
 private:
     explicit Internals(Document*);
     Document* contextDocument() const;
 private:
     explicit Internals(Document*);
     Document* contextDocument() const;
index bb22d8f..ec4144b 100644 (file)
@@ -301,4 +301,6 @@ enum PageOverlayType {
 
     [RaisesException] void installMockPageOverlay(PageOverlayType type);
     [RaisesException] DOMString pageOverlayLayerTreeAsText();
 
     [RaisesException] void installMockPageOverlay(PageOverlayType type);
     [RaisesException] DOMString pageOverlayLayerTreeAsText();
+
+    void setPageMuted(boolean muted);
 };
 };