1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/test/plugin/plugin_windowed_test.h" 6 7 #include "base/logging.h" 8 #include "content/test/plugin/plugin_client.h" 9 10 namespace NPAPIClient { 11 12 WindowedPluginTest::WindowedPluginTest(NPP id, NPNetscapeFuncs *host_functions) 13 : PluginTest(id, host_functions), 14 window_(NULL), done_(false) { 15 } 16 17 WindowedPluginTest::~WindowedPluginTest() { 18 if (window_) 19 DestroyWindow(window_); 20 } 21 22 NPError WindowedPluginTest::SetWindow(NPWindow* pNPWindow) { 23 if (pNPWindow->window == NULL) 24 return NPERR_NO_ERROR; 25 26 if (test_name() == "create_instance_in_paint" && test_id() == "2") { 27 SignalTestCompleted(); 28 return NPERR_NO_ERROR; 29 } 30 31 if (window_) 32 return NPERR_NO_ERROR; 33 34 HWND parent = reinterpret_cast<HWND>(pNPWindow->window); 35 if (!::IsWindow(parent)) { 36 SetError("Invalid arguments passed in"); 37 return NPERR_INVALID_PARAM; 38 } 39 40 if ((test_name() == "create_instance_in_paint" && test_id() == "1") || 41 test_name() == "alert_in_window_message" || 42 test_name() == "set_title_in_paint" || 43 test_name() == "set_title_in_set_window_and_paint") { 44 static ATOM window_class = 0; 45 if (!window_class) { 46 WNDCLASSEX wcex; 47 wcex.cbSize = sizeof(WNDCLASSEX); 48 wcex.style = CS_DBLCLKS; 49 wcex.lpfnWndProc = &NPAPIClient::WindowedPluginTest::WindowProc; 50 wcex.cbClsExtra = 0; 51 wcex.cbWndExtra = 0; 52 wcex.hInstance = GetModuleHandle(NULL); 53 wcex.hIcon = 0; 54 wcex.hCursor = 0; 55 wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW+1); 56 wcex.lpszMenuName = 0; 57 wcex.lpszClassName = L"CreateInstanceInPaintTestWindowClass"; 58 wcex.hIconSm = 0; 59 window_class = RegisterClassEx(&wcex); 60 } 61 62 window_ = CreateWindowEx( 63 WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR, 64 MAKEINTATOM(window_class), 0, 65 WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE , 66 0, 0, 100, 100, parent, 0, GetModuleHandle(NULL), 0); 67 DCHECK(window_); 68 // TODO: this propery leaks. 69 ::SetProp(window_, L"Plugin_Instance", this); 70 } 71 72 if (test_name() == "set_title_in_set_window_and_paint") 73 CallJSFunction(this, "PluginCreated"); 74 75 return NPERR_NO_ERROR; 76 } 77 78 NPError WindowedPluginTest::Destroy() { 79 if (test_name() != "ensure_scripting_works_in_destroy") 80 return NPERR_NO_ERROR; 81 82 // Bug 23706: ensure that scripting works with no asserts. 83 NPObject *window_obj = NULL; 84 HostFunctions()->getvalue(id(), NPNVWindowNPObject,&window_obj); 85 86 if (!window_obj) { 87 SetError("Failed to get NPObject for plugin instance"); 88 } else { 89 std::string script = "javascript:GetMagicNumber()"; 90 NPString script_string; 91 script_string.UTF8Characters = script.c_str(); 92 script_string.UTF8Length = 93 static_cast<unsigned int>(script.length()); 94 95 NPVariant result_var; 96 bool result = HostFunctions()->evaluate( 97 id(), window_obj, &script_string, &result_var); 98 if (!result || 99 result_var.type != NPVariantType_Double || 100 result_var.value.doubleValue != 42.0) { 101 SetError("Failed to script during NPP_Destroy"); 102 } 103 } 104 105 SignalTestCompleted(); 106 return NPERR_NO_ERROR; 107 } 108 109 void WindowedPluginTest::CallJSFunction( 110 WindowedPluginTest* this_ptr, const char* function) { 111 NPIdentifier function_id = this_ptr->HostFunctions()->getstringidentifier( 112 function); 113 114 NPObject *window_obj = NULL; 115 this_ptr->HostFunctions()->getvalue( 116 this_ptr->id(), NPNVWindowNPObject, &window_obj); 117 118 NPVariant rv; 119 this_ptr->HostFunctions()->invoke( 120 this_ptr->id(), window_obj, function_id, NULL, 0, &rv); 121 } 122 123 LRESULT CALLBACK WindowedPluginTest::WindowProc( 124 HWND window, UINT message, WPARAM wparam, LPARAM lparam) { 125 WindowedPluginTest* this_ptr = 126 reinterpret_cast<WindowedPluginTest*> 127 (::GetProp(window, L"Plugin_Instance")); 128 129 if (message == WM_PAINT) { 130 PAINTSTRUCT ps; 131 HDC hdc = BeginPaint(window, &ps); 132 HBRUSH brush = CreateSolidBrush(RGB(255, 0, 0)); 133 HGDIOBJ orig = SelectObject(hdc, brush); 134 RECT r; 135 GetClientRect(window, &r); 136 Rectangle(hdc, 0, 0, r.right, r.bottom); 137 SelectObject(hdc, orig); // restore 138 DeleteObject(brush); 139 EndPaint(window, &ps); 140 } 141 142 if (this_ptr && !this_ptr->done_) { 143 if (this_ptr->test_name() == "create_instance_in_paint" && 144 message == WM_PAINT) { 145 this_ptr->done_ = true; 146 CallJSFunction(this_ptr, "CreateNewInstance"); 147 } else if (this_ptr->test_name() == "alert_in_window_message" && 148 message == WM_PAINT) { 149 this_ptr->done_ = true; 150 // We call this function twice as we want to display two alerts 151 // and verify that we don't hang the browser. 152 CallJSFunction(this_ptr, "CallAlert"); 153 CallJSFunction(this_ptr, "CallAlert"); 154 } else if (this_ptr->test_name() == "set_title_in_paint" && 155 message == WM_PAINT) { 156 this_ptr->done_ = true; 157 CallJSFunction(this_ptr, "SetTitle"); 158 } else if (this_ptr->test_name() == "set_title_in_set_window_and_paint" && 159 message == WM_PAINT) { 160 this_ptr->done_ = true; 161 CallJSFunction(this_ptr, "PluginShown"); 162 } 163 164 if (this_ptr->done_) { 165 ::RemoveProp(window, L"Plugin_Instance"); 166 } 167 } 168 169 return DefWindowProc(window, message, wparam, lparam); 170 } 171 172 } // namespace NPAPIClient 173