FireBreath  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Pages
NpapiPluginWin.cpp
1 /**********************************************************\
2 Original Author: Richard Bateman (taxilian)
3 
4 Created: Dec 3, 2009
5 License: Dual license model; choose one of two:
6  New BSD License
7  http://www.opensource.org/licenses/bsd-license.php
8  - or -
9  GNU Lesser General Public License, version 2.1
10  http://www.gnu.org/licenses/lgpl-2.1.html
11 
12 Copyright 2009 PacketPass, Inc and the Firebreath development team
13 \**********************************************************/
14 
15 #include <boost/algorithm/string.hpp>
16 #include <boost/make_shared.hpp>
17 #include "win_common.h"
18 #include "NpapiTypes.h"
19 #include "PluginCore.h"
20 #include "FactoryBase.h"
21 #include "Win/NpapiPluginWin.h"
22 #include "Win/PluginWindowWin.h"
23 #include "Win/PluginWindowlessWin.h"
24 #include "NpapiPluginFactory.h"
25 #include "PluginInfo.h"
26 #include "precompiled_headers.h" // On windows, everything above this line in PCH
27 
28 #ifdef FBWIN_ASYNCSURFACE
29 
30 #include "Win/NpapiAsyncDrawService.h"
31 
32 struct DrawingModel {
33  const char* name;
34  NPNVariable query;
35  NPDrawingModel model;
36 
37  bool negotiate(const FB::Npapi::NpapiBrowserHostPtr& host, const std::string& requested, boost::function<void(NPDrawingModel)> factory) const
38  {
39  using namespace boost::algorithm;
40  std::vector<std::string> prefs;
41  split(prefs, requested, !is_alnum());
42 
43  bool gotone = false;
44  for (size_t i = 0; !gotone && i < prefs.size(); i++) {
45  const DrawingModel* dm = this;
46  while (dm->name && strcmp(prefs[i].c_str(), dm->name)) dm++;
47 
48  NPBool supported = false;
49  if (dm->name &&
50  NPERR_NO_ERROR == host->GetValue(dm->query, &supported) && supported &&
51  NPERR_NO_ERROR == host->SetValue(NPPVpluginDrawingModel, (void*) dm->model))
52  {
53  factory(dm->model);
54  gotone = true;
55  }
56  }
57  return gotone;
58  }
59 
60 };
61 
62 #define FB_DRAWING_MODEL(x) { #x, NPNVsupports##x##Bool, NPDrawingModel##x }
63 #define FB_DRAWING_MODEL_FBLEGACYNAME(x, f) { "NPDrawingModel"#x, NPNVsupports##x##Bool, NPDrawingModel##x }
64 #define FB_DRAWING_MODEL_END_LIST { 0, (NPNVariable) 0, (NPDrawingModel) 0 }
65 
66 static const DrawingModel g_supportedModels[] = {
67  // FB_DRAWING_MODEL(AsyncBitmapSurface), // still todo
68  FB_DRAWING_MODEL(AsyncWindowsDXGISurface),
69  FB_DRAWING_MODEL_END_LIST
70 };
71 
72 void FB::Npapi::NpapiPluginWin::pluginWindowFactory(NPDrawingModel model)
73 {
74  // todo: support AsyncBitmapSurface as well
75  AsyncDrawServicePtr asd = boost::make_shared<NpapiAsyncDrawService>(m_npHost);
76  PluginWindow* pw = getFactoryInstance()->createPluginWindowless(WindowContextWindowless(NULL, asd));
77  pluginWin.swap(boost::scoped_ptr<PluginWindow>(pw));
78  m_drawingModel = model;
79 }
80 
81 #endif
82 
83 using namespace FB::Npapi;
84 
85 extern std::string g_dllPath;
86 
87 FB::Npapi::NpapiPluginPtr FB::Npapi::createNpapiPlugin(const FB::Npapi::NpapiBrowserHostPtr& host, const std::string& mimetype)
88 {
89  return boost::make_shared<NpapiPluginWin>(host, mimetype);
90 }
91 
92 NpapiPluginWin::NpapiPluginWin(const NpapiBrowserHostPtr& host, const std::string& mimetype)
93  : NpapiPlugin(host, mimetype)
94  , m_drawingModel((NPDrawingModel)-1)
95 {
96  PluginCore::setPlatform("Windows", "NPAPI");
97  setFSPath(g_dllPath);
98 }
99 
100 NpapiPluginWin::~NpapiPluginWin()
101 {
102  pluginMain->ClearWindow();
103 }
104 
105 void NpapiPluginWin::init(NPMIMEType pluginType, int16_t argc, char* argn[], char *argv[])
106 {
107  NpapiPlugin::init(pluginType, argc, argn, argv);
108 
109  if (!FB::pluginGuiEnabled() || pluginMain->isWindowless()) {
110  /* Windowless plugins require negotiation with the browser.
111  * If the plugin does not set this value it is assumed to be
112  * a windowed plugin.
113  * See: https://developer.mozilla.org/en/Gecko_Plugin_API_Reference/Drawing_and_Event_Handling
114  */
115  m_npHost->SetValue(NPPVpluginWindowBool, (void*)false);
116  m_npHost->SetValue(NPPVpluginTransparentBool, (void*)true); // Set transparency to true
117  }
118 
119 #ifdef FBWIN_ASYNCSURFACE
120  bool negotiated = g_supportedModels->negotiate(
121  m_npHost,
122  pluginMain->negotiateDrawingModel(),
123  boost::bind(&NpapiPluginWin::pluginWindowFactory, this, _1));
124 #endif
125  if (pluginWin)
126  {
127  pluginMain->SetWindow(pluginWin.get());
128  }
129 }
130 
131 void NpapiPluginWin::invalidateWindow( uint32_t left, uint32_t top, uint32_t right, uint32_t bottom )
132 {
133  NPRect r = { top, left, bottom, right };
134  if (!m_npHost->isMainThread()) {
135  m_npHost->ScheduleOnMainThread(m_npHost, boost::bind(&NpapiBrowserHost::InvalidateRect2, m_npHost, r));
136  } else {
137  m_npHost->InvalidateRect(&r);
138  }
139 }
140 
141 NPError NpapiPluginWin::SetWindow(NPWindow* window)
142 {
143  // If window == NULL then our window is gone. Stop drawing.
144  // If window->window == NULL and we're a windowed plugin then the window is gone; otherwise not
145  if(window == NULL || (window->window == NULL && window->type != NPWindowTypeDrawable)) {
146  // Our window is gone
147  if(pluginMain != NULL) {
148  // Destroy our FireBreath window
149  pluginMain->ClearWindow();
150  pluginWin.reset();
151  }
152  return NPERR_NO_ERROR;
153  }
154  if (!pluginGuiEnabled())
155  return NPERR_NO_ERROR;
156 
157  if (m_drawingModel == NPDrawingModelAsyncWindowsDXGISurface) {
158  PluginWindowlessWin* win = dynamic_cast<PluginWindowlessWin*>(pluginWin.get());
159  assert(win);
160  if (win) {
161  win->setWindowPosition(window->x, window->y, window->width, window->height);
162  }
163  } else
164  // Code here diverges depending on if
165  // the plugin is windowed or windowless.
166  if(pluginMain->isWindowless()) {
167  assert(window->type == NPWindowTypeDrawable);
168  PluginWindowlessWin* win = dynamic_cast<PluginWindowlessWin*>(pluginWin.get());
169 
170  if(win == NULL && pluginWin != NULL) {
171  // We've received a window of a different type than the
172  // window we have been using up until now.
173  // This is unlikely/impossible, but it's worth checking for.
174  pluginMain->ClearWindow();
175  pluginWin.reset();
176  }
177 
178  if(pluginWin == NULL) {
179  // Create new window
180  win = getFactoryInstance()->createPluginWindowless(FB::WindowContextWindowless(NULL));
181  HWND browserHWND;
182  m_npHost->GetValue(NPNVnetscapeWindow, (void*)&browserHWND);
183  win->setHWND(browserHWND);
184  win->setWindowPosition(window->x, window->y, window->width, window->height);
185  win->setWindowClipping(window->clipRect.top, window->clipRect.left,
186  window->clipRect.bottom, window->clipRect.right);
187  win->setInvalidateWindowFunc(boost::bind(&NpapiPluginWin::invalidateWindow, this, _1, _2, _3, _4));
188  pluginMain->SetWindow(win);
189  pluginWin.reset(win);
190  } else if (win) {
191  win->setWindowPosition(window->x, window->y, window->width, window->height);
192  win->setWindowClipping(window->clipRect.top, window->clipRect.left,
193  window->clipRect.bottom, window->clipRect.right);
194  }
195  } else {
196  assert(window->type == NPWindowTypeWindow);
197  PluginWindowWin* win = dynamic_cast<PluginWindowWin*>(pluginWin.get());
198  // Check to see if we've received a new HWND (new window)
199  if(win != NULL && win->getHWND() != (HWND)window->window) {
200  pluginMain->ClearWindow();
201  pluginWin.reset() ;
202  } else if(win == NULL && pluginWin != NULL) {
203  // We've received a window of a different type than the
204  // window we have been using up until now.
205  // This is unlikely/impossible, but it's worth checking for.
206  pluginMain->ClearWindow();
207  pluginWin.reset();
208  }
209 
210  if(pluginWin == NULL) {
211  // Sanity check
212  assert(::IsWindow((HWND)window->window));
213  // Create new window
214  HWND browserHWND;
215  m_npHost->GetValue(NPNVnetscapeWindow, (void*)&browserHWND);
216  win = getFactoryInstance()->createPluginWindowWin(FB::WindowContextWin((HWND)window->window));
217  win->setBrowserHWND(browserHWND);
218  pluginMain->SetWindow(win);
219  pluginWin.reset(win);
220  }
221  }
222 
223  return NPERR_NO_ERROR;
224 }
225 
226 int16_t NpapiPluginWin::HandleEvent(void* event) {
227  PluginWindowlessWin* win = dynamic_cast<PluginWindowlessWin*>(pluginWin.get());
228  if(win != NULL) {
229  LRESULT lRes(0);
230  NPEvent* evt(reinterpret_cast<NPEvent*>(event));
231  if (evt->event == WM_PAINT) { //special handle drawing, as we need to pass the draw bounds through the layers
232  FB::Rect bounds;
233  if (evt->lParam) { // some browsers pass through bounds in lParam, but Safari does not (as of 5.0.5)
234  RECT *prc = (RECT*) evt->lParam; // not 64-bit safe, but it's how NPAPI works
235  bounds.top = prc->top;
236  bounds.left = prc->left;
237  bounds.bottom = prc->bottom;
238  bounds.right = prc->right;
239  } else {
240  bounds = win->getWindowPosition();
241  }
242  return win->HandleDraw((HDC)evt->wParam, bounds);
243  } else if (win->HandleEvent(evt->event, static_cast<uint32_t>(evt->wParam), evt->lParam, lRes)) {
244  return boost::numeric_cast<int16_t>(lRes);
245  }
246  }
247  return false;
248 }
249 
static void setPlatform(const std::string &os, const std::string &browser)
Called by the browser when the Operating System and Browser are known.
Definition: PluginCore.cpp:36