https://bugs.webkit.org/show_bug.cgi?id=138105
Reviewed by Anders Carlsson.
Source/WebCore:
Add the new NPNVmuteAudioBool NPNVariable.
Test: platform/mac-wk2/plugins/muted-state.html
* plugins/npapi.h:
Source/WebKit2:
Handle the setting of NPNVmuteAudioBool on the plug-in.
* PluginProcess/PluginControllerProxy.cpp:
(WebKit::PluginControllerProxy::PluginControllerProxy):
Initialize m_isMuted.
(WebKit::PluginControllerProxy::mutedStateChanged):
Tell the plugin about the new muted state.
* PluginProcess/PluginControllerProxy.h:
* PluginProcess/PluginControllerProxy.messages.in:
Add the MutedStateChanged message.
* PluginProcess/PluginCreationParameters.cpp:
(WebKit::PluginCreationParameters::PluginCreationParameters):
Initialize isMuted.
(WebKit::PluginCreationParameters::encode):
Handle isMuted.
(WebKit::PluginCreationParameters::decode):
Ditto.
* PluginProcess/PluginCreationParameters.h:
* WebProcess/Plugins/Netscape/NetscapeBrowserFuncs.cpp:
(WebKit::NPN_GetValue):
Get the plug-in's muted state.
* WebProcess/Plugins/Netscape/NetscapePlugin.cpp:
(WebKit::NetscapePlugin::isMuted):
Get the muted state from PluginControllerProxy.
(WebKit::NetscapePlugin::mutedStateChanged):
Call NPP_SetValue with NPNVmuteAudioBool and the updated muted state.
* WebProcess/Plugins/Netscape/NetscapePlugin.h:
* WebProcess/Plugins/Plugin.h:
(WebKit::Plugin::mutedStateChanged):
* WebProcess/Plugins/PluginController.h:
* WebProcess/Plugins/PluginProxy.cpp:
(WebKit::PluginProxy::initialize):
Set m_pendingPluginCreationParameters->isMuted.
(WebKit::PluginProxy::mutedStateChanged):
Send the MutedStateChanged message to the plugin process.
* WebProcess/Plugins/PluginProxy.h:
* WebProcess/Plugins/PluginView.cpp:
(WebKit::PluginView::pageMutedStateDidChange):
Call Plugin::mutedStateChanged() with the page's muted state.
(WebKit::PluginView::isMuted):
Get the page's current muted state.
* WebProcess/Plugins/PluginView.h:
Tools:
Add a new plug-in test for the mute API.
* DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj:
* DumpRenderTree/TestNetscapePlugIn/Tests/mac/SetMuted.cpp: Added.
(SetMuted::SetMuted):
(SetMuted::isMuted):
(SetMuted::cachedIsMuted):
(SetMuted::ScriptableObject::hasProperty):
(SetMuted::ScriptableObject::getProperty):
(SetMuted::ScriptableObject::pluginTest):
(SetMuted::NPP_New):
(SetMuted::NPP_GetValue):
(SetMuted::NPP_SetValue):
LayoutTests:
* platform/mac-wk2/plugins/muted-state-expected.txt: Added.
* platform/mac-wk2/plugins/muted-state.html: Added.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@176039
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2014-11-05 Ada Chan <adachan@apple.com>
+
+ Implement new plug-in API for muting plug-ins
+ https://bugs.webkit.org/show_bug.cgi?id=138105
+
+ Reviewed by Anders Carlsson.
+
+ * platform/mac-wk2/plugins/muted-state-expected.txt: Added.
+ * platform/mac-wk2/plugins/muted-state.html: Added.
+
2014-11-12 Alexey Proskuryakov <ap@apple.com>
Some platform/mac text expectation cleanup.
--- /dev/null
+Tests that the mute API implementation works as expected. This test needs to be run through WebKitTestRunner.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS plugin1.isMuted is false
+PASS plugin1.cachedIsMuted is false
+PASS plugin1.isMuted is true
+PASS plugin1.cachedIsMuted is true
+PASS plugin2.isMuted is true
+PASS plugin2.cachedIsMuted is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+<script>
+description("Tests that the mute API implementation works as expected. This test needs to be run through WebKitTestRunner.");
+
+jsTestIsAsync = true;
+
+function createTestPlugin(testName)
+{
+ var plugin = document.createElement("embed");
+ plugin.type = "application/x-webkit-test-netscape";
+ plugin.setAttribute('test', testName);
+
+ return plugin;
+}
+
+function runTest()
+{
+ if (!window.testRunner) {
+ debug("This test can only run from within DumpRenderTree because it requires TestNetscapePlugin.\n");
+ return;
+ }
+
+ plugin1 = createTestPlugin('set-muted');
+ document.body.appendChild(plugin1);
+
+ shouldBeFalse("plugin1.isMuted");
+ shouldBeFalse("plugin1.cachedIsMuted");
+
+ // Now set page to be muted.
+ if (window.internals)
+ window.internals.setPageMuted(true);
+
+ shouldBeTrue("plugin1.isMuted");
+ shouldBeTrue("plugin1.cachedIsMuted");
+
+ plugin2 = createTestPlugin('set-muted');
+ document.body.appendChild(plugin2);
+ shouldBeTrue("plugin2.isMuted");
+ shouldBeTrue("plugin2.cachedIsMuted");
+
+ finishJSTest();
+}
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+</head>
+<body onload="runTest()">
+</body>
+2014-11-05 Ada Chan <adachan@apple.com>
+
+ Implement new plug-in API for muting plug-ins
+ https://bugs.webkit.org/show_bug.cgi?id=138105
+
+ Reviewed by Anders Carlsson.
+
+ Add the new NPNVmuteAudioBool NPNVariable.
+
+ Test: platform/mac-wk2/plugins/muted-state.html
+
+ * plugins/npapi.h:
+
2014-11-12 Tim Horton <timothy_horton@apple.com>
Need to show the text indicator when Data Detectors shows a popover
, NPNVsupportsCompositingCoreAnimationPluginsBool = 74656 /* TRUE if the browser supports
CA model compositing */
#endif /* XP_MACOSX */
+
+ , NPNVmuteAudioBool = 4000
+
} NPNVariable;
typedef enum {
+2014-11-05 Ada Chan <adachan@apple.com>
+
+ Implement new plug-in API for muting plug-ins
+ https://bugs.webkit.org/show_bug.cgi?id=138105
+
+ Reviewed by Anders Carlsson.
+
+ Handle the setting of NPNVmuteAudioBool on the plug-in.
+
+ * PluginProcess/PluginControllerProxy.cpp:
+ (WebKit::PluginControllerProxy::PluginControllerProxy):
+ Initialize m_isMuted.
+ (WebKit::PluginControllerProxy::mutedStateChanged):
+ Tell the plugin about the new muted state.
+ * PluginProcess/PluginControllerProxy.h:
+ * PluginProcess/PluginControllerProxy.messages.in:
+ Add the MutedStateChanged message.
+ * PluginProcess/PluginCreationParameters.cpp:
+ (WebKit::PluginCreationParameters::PluginCreationParameters):
+ Initialize isMuted.
+ (WebKit::PluginCreationParameters::encode):
+ Handle isMuted.
+ (WebKit::PluginCreationParameters::decode):
+ Ditto.
+ * PluginProcess/PluginCreationParameters.h:
+ * WebProcess/Plugins/Netscape/NetscapeBrowserFuncs.cpp:
+ (WebKit::NPN_GetValue):
+ Get the plug-in's muted state.
+ * WebProcess/Plugins/Netscape/NetscapePlugin.cpp:
+ (WebKit::NetscapePlugin::isMuted):
+ Get the muted state from PluginControllerProxy.
+ (WebKit::NetscapePlugin::mutedStateChanged):
+ Call NPP_SetValue with NPNVmuteAudioBool and the updated muted state.
+ * WebProcess/Plugins/Netscape/NetscapePlugin.h:
+ * WebProcess/Plugins/Plugin.h:
+ (WebKit::Plugin::mutedStateChanged):
+ * WebProcess/Plugins/PluginController.h:
+ * WebProcess/Plugins/PluginProxy.cpp:
+ (WebKit::PluginProxy::initialize):
+ Set m_pendingPluginCreationParameters->isMuted.
+ (WebKit::PluginProxy::mutedStateChanged):
+ Send the MutedStateChanged message to the plugin process.
+ * WebProcess/Plugins/PluginProxy.h:
+ * WebProcess/Plugins/PluginView.cpp:
+ (WebKit::PluginView::pageMutedStateDidChange):
+ Call Plugin::mutedStateChanged() with the page's muted state.
+ (WebKit::PluginView::isMuted):
+ Get the page's current muted state.
+ * WebProcess/Plugins/PluginView.h:
+
2014-11-12 Tim Horton <timothy_horton@apple.com>
Two action menu item titles are swapped
, m_pluginInstanceID(creationParameters.pluginInstanceID)
, m_userAgent(creationParameters.userAgent)
, m_isPrivateBrowsingEnabled(creationParameters.isPrivateBrowsingEnabled)
+ , m_isMuted(creationParameters.isMuted)
, m_isAcceleratedCompositingEnabled(creationParameters.isAcceleratedCompositingEnabled)
, m_isInitializing(false)
, m_isVisible(false)
m_plugin->privateBrowsingStateChanged(isPrivateBrowsingEnabled);
}
+void PluginControllerProxy::mutedStateChanged(bool isMuted)
+{
+ if (m_isMuted == isMuted)
+ return;
+
+ m_isMuted = isMuted;
+ m_plugin->mutedStateChanged(isMuted);
+}
+
void PluginControllerProxy::getFormValue(bool& returnValue, String& formValue)
{
returnValue = m_plugin->getFormValue(formValue);
virtual String cookiesForURL(const String&) override;
virtual void setCookiesForURL(const String& urlString, const String& cookieString) override;
virtual bool isPrivateBrowsingEnabled() override;
+ virtual bool isMuted() const override { return m_isMuted; }
virtual bool getAuthenticationInfo(const WebCore::ProtectionSpace&, String& username, String& password) override;
virtual void protectPluginFromDestruction() override;
virtual void unprotectPluginFromDestruction() override;
void storageBlockingStateChanged(bool);
void privateBrowsingStateChanged(bool);
+ void mutedStateChanged(bool);
void getFormValue(bool& returnValue, String& formValue);
void platformInitialize(const PluginCreationParameters&);
String m_userAgent;
bool m_storageBlockingEnabled;
bool m_isPrivateBrowsingEnabled;
+ bool m_isMuted;
bool m_isAcceleratedCompositingEnabled;
bool m_isInitializing;
bool m_isVisible;
# Gets the string representating the form value of the plug-in
GetFormValue() -> (bool returnValue, String formValue)
+
+ # Sent when the browser wants to mute or unmute the plugin.
+ MutedStateChanged(bool muted)
}
#endif
, windowNPObjectID(0)
, contentsScaleFactor(1)
, isPrivateBrowsingEnabled(false)
+ , isMuted(false)
, asynchronousCreationIncomplete(false)
, artificialPluginInitializationDelayEnabled(false)
, isAcceleratedCompositingEnabled(false)
encoder << userAgent;
encoder << contentsScaleFactor;
encoder << isPrivateBrowsingEnabled;
+ encoder << isMuted;
encoder << asynchronousCreationIncomplete;
encoder << artificialPluginInitializationDelayEnabled;
encoder << isAcceleratedCompositingEnabled;
if (!decoder.decode(result.isPrivateBrowsingEnabled))
return false;
+ if (!decoder.decode(result.isMuted))
+ return false;
+
if (!decoder.decode(result.asynchronousCreationIncomplete))
return false;
// Whether private browsing is enabled at the time of instantiation.
bool isPrivateBrowsingEnabled;
+
+ // Whether the plugin should be muted.
+ bool isMuted;
// If requesting synchronous initialization, whether this plugin had previously been requested asynchronously
bool asynchronousCreationIncomplete;
*(NPBool*)value = plugin->isPrivateBrowsingEnabled();
break;
}
+
+ case NPNVmuteAudioBool: {
+ RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
+ *(NPBool*)value = plugin->isMuted();
+ break;
+ }
#if PLATFORM(COCOA)
case NPNVsupportsCoreGraphicsBool:
// Always claim to support the Core Graphics drawing model.
return controller()->isPrivateBrowsingEnabled();
}
+bool NetscapePlugin::isMuted() const
+{
+ return controller()->isMuted();
+}
+
NPObject* NetscapePlugin::windowScriptNPObject()
{
return controller()->windowScriptNPObject();
return true;
}
+void NetscapePlugin::mutedStateChanged(bool muted)
+{
+ NPBool value = muted;
+ NPP_SetValue(NPNVmuteAudioBool, &value);
+}
+
#if !PLATFORM(COCOA)
void NetscapePlugin::windowFocusChanged(bool)
static void setException(const String&);
bool evaluate(NPObject*, const String&scriptString, NPVariant* result);
bool isPrivateBrowsingEnabled();
+ bool isMuted() const;
static void setSetExceptionFunction(void (*)(const String&));
virtual String getSelectionString() const override { return String(); }
+ virtual void mutedStateChanged(bool) override;
+
void updateNPNPrivateMode();
#if PLUGIN_ARCHITECTURE(WIN)
virtual WebCore::AudioHardwareActivityType audioHardwareActivity() const { return WebCore::AudioHardwareActivityType::Unknown; }
+ virtual void mutedStateChanged(bool) { }
+
protected:
Plugin();
// Called by the Netscape plug-in when it starts or stops playing audio.
virtual void setPluginIsPlayingAudio(bool) = 0;
+
+ // Returns whether the plugin should be muted.
+ virtual bool isMuted() const = 0;
#endif
// Set the statusbar text.
m_pendingPluginCreationParameters->userAgent = controller()->userAgent();
m_pendingPluginCreationParameters->contentsScaleFactor = contentsScaleFactor();
m_pendingPluginCreationParameters->isPrivateBrowsingEnabled = controller()->isPrivateBrowsingEnabled();
+ m_pendingPluginCreationParameters->isMuted = controller()->isMuted();
m_pendingPluginCreationParameters->artificialPluginInitializationDelayEnabled = controller()->artificialPluginInitializationDelayEnabled();
m_pendingPluginCreationParameters->isAcceleratedCompositingEnabled = controller()->isAcceleratedCompositingEnabled();
m_connection->connection()->send(Messages::PluginControllerProxy::PrivateBrowsingStateChanged(isPrivateBrowsingEnabled), m_pluginInstanceID);
}
+void PluginProxy::mutedStateChanged(bool isMuted)
+{
+ m_connection->connection()->send(Messages::PluginControllerProxy::MutedStateChanged(isMuted), m_pluginInstanceID);
+}
+
bool PluginProxy::getFormValue(String& formValue)
{
bool returnValue;
virtual void contentsScaleFactorChanged(float);
virtual void storageBlockingStateChanged(bool);
virtual void privateBrowsingStateChanged(bool);
+ virtual void mutedStateChanged(bool) override;
virtual bool getFormValue(String& formValue);
virtual bool handleScroll(WebCore::ScrollDirection, WebCore::ScrollGranularity);
virtual WebCore::Scrollbar* horizontalScrollbar();
void PluginView::pageMutedStateDidChange()
{
- // FIXME: To be implemented (https://bugs.webkit.org/show_bug.cgi?id=138105).
+ // The plug-in can be null here if it failed to initialize.
+ if (!m_isInitialized || !m_plugin)
+ return;
+
+ m_plugin->mutedStateChanged(isMuted());
}
bool PluginView::isPluginVisible()
m_pluginIsPlayingAudio = pluginIsPlayingAudio;
m_pluginElement->document().updateIsPlayingAudio();
}
+
+bool PluginView::isMuted() const
+{
+ if (!frame() || !frame()->page())
+ return false;
+
+ return frame()->page()->isMuted();
+}
#endif
void PluginView::setStatusbarText(const String& statusbarText)
virtual NPObject* pluginElementNPObject() override;
virtual bool evaluate(NPObject*, const String& scriptString, NPVariant* result, bool allowPopups) override;
virtual void setPluginIsPlayingAudio(bool) override;
+ virtual bool isMuted() const override;
#endif
virtual void setStatusbarText(const String&) override;
virtual bool isAcceleratedCompositingEnabled() override;
+2014-11-05 Ada Chan <adachan@apple.com>
+
+ Implement new plug-in API for muting plug-ins
+ https://bugs.webkit.org/show_bug.cgi?id=138105
+
+ Reviewed by Anders Carlsson.
+
+ Add a new plug-in test for the mute API.
+
+ * DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj:
+ * DumpRenderTree/TestNetscapePlugIn/Tests/mac/SetMuted.cpp: Added.
+ (SetMuted::SetMuted):
+ (SetMuted::isMuted):
+ (SetMuted::cachedIsMuted):
+ (SetMuted::ScriptableObject::hasProperty):
+ (SetMuted::ScriptableObject::getProperty):
+ (SetMuted::ScriptableObject::pluginTest):
+ (SetMuted::NPP_New):
+ (SetMuted::NPP_GetValue):
+ (SetMuted::NPP_SetValue):
+
2014-11-12 Philippe Normand <pnormand@igalia.com>
Unreviewed, GTK gardening.
515F429C15C07872007C8F90 /* PluginScriptableObjectOverridesAllProperties.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 515F429B15C07872007C8F90 /* PluginScriptableObjectOverridesAllProperties.cpp */; };
5185F6B210714E07007AA393 /* HistoryDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5185F69F10714A57007AA393 /* HistoryDelegate.mm */; };
51CACBD815D96FD000EB53A2 /* EvaluateJSWithinNPP_New.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51CACBD715D96FD000EB53A2 /* EvaluateJSWithinNPP_New.cpp */; };
+ 520206CF1A0ADA5900AD5154 /* SetMuted.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 520206CE1A0ADA5900AD5154 /* SetMuted.cpp */; };
53CBB832134E42F3001CE6A4 /* CyclicRedundancyCheck.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53CBB830134E42F3001CE6A4 /* CyclicRedundancyCheck.cpp */; };
5DB9AC970F722C3600684641 /* AHEM____.TTF in Copy Font Files */ = {isa = PBXBuildFile; fileRef = AA7F10C20CB3C1030003BDC9 /* AHEM____.TTF */; };
5DB9AC980F722C3600684641 /* WebKitWeightWatcher100.ttf in Copy Font Files */ = {isa = PBXBuildFile; fileRef = 375F09710DAC3CB600C8B4E5 /* WebKitWeightWatcher100.ttf */; };
5185F69E10714A57007AA393 /* HistoryDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HistoryDelegate.h; path = mac/HistoryDelegate.h; sourceTree = "<group>"; };
5185F69F10714A57007AA393 /* HistoryDelegate.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; name = HistoryDelegate.mm; path = mac/HistoryDelegate.mm; sourceTree = "<group>"; };
51CACBD715D96FD000EB53A2 /* EvaluateJSWithinNPP_New.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = EvaluateJSWithinNPP_New.cpp; path = TestNetscapePlugIn/Tests/EvaluateJSWithinNPP_New.cpp; sourceTree = SOURCE_ROOT; };
+ 520206CE1A0ADA5900AD5154 /* SetMuted.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SetMuted.cpp; sourceTree = "<group>"; };
53CBB830134E42F3001CE6A4 /* CyclicRedundancyCheck.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CyclicRedundancyCheck.cpp; sourceTree = "<group>"; };
53CBB831134E42F3001CE6A4 /* CyclicRedundancyCheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CyclicRedundancyCheck.h; sourceTree = "<group>"; };
5DE8AE4313A2C15800D6A37D /* libWebCoreTestSupport.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libWebCoreTestSupport.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
children = (
1A66C34F14576A920099A115 /* ContentsScaleFactor.cpp */,
1A31EB3713466AC100017372 /* ConvertPoint.cpp */,
+ 520206CE1A0ADA5900AD5154 /* SetMuted.cpp */,
1A14C8A31406DE0400B254F7 /* SupportsCarbonEventModel.cpp */,
);
path = mac;
51CACBD815D96FD000EB53A2 /* EvaluateJSWithinNPP_New.cpp in Sources */,
4AD6A11413C8124000EA9737 /* FormValue.cpp in Sources */,
1AFF66BC137DEFD200791696 /* GetURLNotifyWithURLThatFailsToLoad.cpp in Sources */,
+ 520206CF1A0ADA5900AD5154 /* SetMuted.cpp in Sources */,
1A5CC1F5137DD2EC00A5D7E7 /* GetURLWithJavaScriptURL.cpp in Sources */,
1A3E28AA1311D73B00501349 /* GetURLWithJavaScriptURLDestroyingPlugin.cpp in Sources */,
1AD4CB2212A6D1350027A7AF /* GetUserAgentWithNullNPPFromNPPNew.cpp in Sources */,
--- /dev/null
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "PluginTest.h"
+
+using namespace std;
+
+class SetMuted : public PluginTest {
+public:
+ SetMuted(NPP npp, const string& identifier)
+ : PluginTest(npp, identifier)
+ , m_cachedIsMuted(false)
+ {
+ }
+
+private:
+ bool isMuted()
+ {
+ NPBool muted = FALSE;
+ NPN_GetValue(NPNVmuteAudioBool, &muted);
+ return muted;
+ }
+
+ bool cachedIsMuted()
+ {
+ return m_cachedIsMuted;
+ }
+
+ class ScriptableObject : public Object<ScriptableObject> {
+ public:
+ bool hasProperty(NPIdentifier propertyName)
+ {
+ return identifierIs(propertyName, "isMuted")
+ || identifierIs(propertyName, "cachedIsMuted");
+ }
+
+ bool getProperty(NPIdentifier propertyName, NPVariant* result)
+ {
+ if (identifierIs(propertyName, "isMuted")) {
+ BOOLEAN_TO_NPVARIANT(pluginTest()->isMuted(), *result);
+ return true;
+ }
+ if (identifierIs(propertyName, "cachedIsMuted")) {
+ BOOLEAN_TO_NPVARIANT(pluginTest()->cachedIsMuted(), *result);
+ return true;
+ }
+ return false;
+ }
+
+ private:
+ SetMuted* pluginTest() const { return static_cast<SetMuted*>(Object<ScriptableObject>::pluginTest()); }
+ };
+
+ virtual NPError NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData *saved)
+ {
+ m_cachedIsMuted = isMuted();
+ return NPERR_NO_ERROR;
+ }
+
+ virtual NPError NPP_GetValue(NPPVariable variable, void* value)
+ {
+ if (variable != NPPVpluginScriptableNPObject)
+ return NPERR_GENERIC_ERROR;
+
+ *(NPObject**)value = ScriptableObject::create(this);
+
+ return NPERR_NO_ERROR;
+ }
+
+ virtual NPError NPP_SetValue(NPNVariable variable, void* value)
+ {
+ switch (variable) {
+ case NPNVmuteAudioBool:
+ m_cachedIsMuted = *(NPBool*)value;
+ return NPERR_NO_ERROR;
+ default:
+ return NPERR_GENERIC_ERROR;
+ }
+
+ }
+ bool m_cachedIsMuted;
+};
+
+static PluginTest::Register<SetMuted> setMuted("set-muted");