1 /* 2 * Copyright (C) 2011 Apple 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 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "PluginTest.h" 27 28 #include "PluginObject.h" 29 30 using namespace std; 31 32 // NPP_SetWindow should be called with a null window handle as destruction begins on non-Mac platforms. 33 34 class NPPSetWindowCalledDuringDestruction : public PluginTest { 35 public: 36 NPPSetWindowCalledDuringDestruction(NPP, const string& identifier); 37 38 void setWillBeDestroyed() { m_willBeDestroyed = true; } 39 40 private: 41 struct ScriptObject : Object<ScriptObject> { 42 bool hasMethod(NPIdentifier); 43 bool invoke(NPIdentifier, const NPVariant*, uint32_t, NPVariant*); 44 }; 45 46 virtual NPError NPP_GetValue(NPPVariable, void*); 47 virtual NPError NPP_SetWindow(NPP, NPWindow*); 48 virtual NPError NPP_Destroy(NPSavedData**); 49 50 bool m_willBeDestroyed; 51 bool m_setWindowCalledBeforeDestruction; 52 bool m_setWindowCalledDuringDestruction; 53 }; 54 55 static PluginTest::Register<NPPSetWindowCalledDuringDestruction> registrar("npp-set-window-called-during-destruction"); 56 57 NPPSetWindowCalledDuringDestruction::NPPSetWindowCalledDuringDestruction(NPP npp, const string& identifier) 58 : PluginTest(npp, identifier) 59 , m_willBeDestroyed(false) 60 , m_setWindowCalledBeforeDestruction(false) 61 , m_setWindowCalledDuringDestruction(false) 62 { 63 } 64 65 NPError NPPSetWindowCalledDuringDestruction::NPP_GetValue(NPPVariable variable, void* value) 66 { 67 if (variable != NPPVpluginScriptableNPObject) 68 return NPERR_GENERIC_ERROR; 69 70 *static_cast<NPObject**>(value) = ScriptObject::create(this); 71 72 return NPERR_NO_ERROR; 73 } 74 75 NPError NPPSetWindowCalledDuringDestruction::NPP_SetWindow(NPP, NPWindow* window) 76 { 77 if (m_willBeDestroyed) { 78 m_setWindowCalledDuringDestruction = true; 79 if (!m_setWindowCalledBeforeDestruction) { 80 log("Fail: setWillBeDestroyed() was called before the initial NPP_SetWindow call"); 81 return NPERR_NO_ERROR; 82 } 83 #ifndef XP_MACOSX 84 if (window->window) 85 log("Fail: NPP_SetWindow passed a non-null window during plugin destruction"); 86 #endif 87 return NPERR_NO_ERROR; 88 } 89 90 if (m_setWindowCalledBeforeDestruction) { 91 log("Fail: NPP_SetWindow called more than once before plugin destruction"); 92 return NPERR_NO_ERROR; 93 } 94 95 m_setWindowCalledBeforeDestruction = true; 96 return NPERR_NO_ERROR; 97 } 98 99 NPError NPPSetWindowCalledDuringDestruction::NPP_Destroy(NPSavedData**) 100 { 101 #ifdef XP_MACOSX 102 bool shouldHaveBeenCalledDuringDestruction = false; 103 #else 104 bool shouldHaveBeenCalledDuringDestruction = true; 105 #endif 106 107 if (m_setWindowCalledDuringDestruction == shouldHaveBeenCalledDuringDestruction) 108 log("Success: NPP_SetWindow %s called during plugin destruction", shouldHaveBeenCalledDuringDestruction ? "was" : "was not"); 109 else 110 log("Fail: NPP_SetWindow %s called during plugin destruction", shouldHaveBeenCalledDuringDestruction ? "was not" : "was"); 111 112 return NPERR_NO_ERROR; 113 } 114 115 bool NPPSetWindowCalledDuringDestruction::ScriptObject::hasMethod(NPIdentifier methodName) 116 { 117 return methodName == pluginTest()->NPN_GetStringIdentifier("setWillBeDestroyed"); 118 } 119 120 bool NPPSetWindowCalledDuringDestruction::ScriptObject::invoke(NPIdentifier identifier, const NPVariant*, uint32_t, NPVariant*) 121 { 122 assert(identifier == pluginTest()->NPN_GetStringIdentifier("setWillBeDestroyed")); 123 static_cast<NPPSetWindowCalledDuringDestruction*>(pluginTest())->setWillBeDestroyed(); 124 return true; 125 } 126