summaryrefslogtreecommitdiffstats
path: root/webkit/glue/plugins/webplugin_delegate_impl.h
blob: 3b774e8ec989e982da6d2c964195c22bcf1517b4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
// Copyright 2008, Google 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:
//
//    * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//    * 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.
//    * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
// OWNER OR 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.

#ifndef WEBKIT_GLUE_PLUGIN_WEBPLUGIN_DELEGATE_IMPL_H__
#define WEBKIT_GLUE_PLUGIN_WEBPLUGIN_DELEGATE_IMPL_H__

#include <string>
#include <list>

#include "base/ref_counted.h"
#include "base/task.h"
#include "webkit/glue/webplugin_delegate.h"
#include "third_party/npapi/bindings/npapi.h"
#include "webkit/glue/webcursor.h"

namespace NPAPI {
  class PluginInstance;
};

// An implementation of WebPluginDelegate that proxies all calls to
// the plugin process.
class WebPluginDelegateImpl : public WebPluginDelegate {
 public:
  static WebPluginDelegateImpl* Create(const std::wstring& filename,
                                       const std::string& mime_type,
                                       HWND containing_window);
  static bool IsPluginDelegateWindow(HWND window);
  static bool GetPluginNameFromWindow(HWND window, std::wstring *plugin_name);

  // Returns true if the window handle passed in is that of the dummy
  // activation window for windowless plugins.
  static bool IsDummyActivationWindow(HWND window);

  // WebPluginDelegate implementation
  virtual void PluginDestroyed();
  virtual bool Initialize(const GURL& url,
                          char** argn,
                          char** argv,
                          int argc,
                          WebPlugin* plugin,
                          bool load_manually);
  virtual void UpdateGeometry(const gfx::Rect& window_rect,
                              const gfx::Rect& clip_rect, bool visible);
  virtual void Paint(HDC hdc, const gfx::Rect& rect);
  virtual void Print(HDC hdc);
  virtual void SetFocus();  // only called when windowless
// only called when windowless
  virtual bool HandleEvent(NPEvent* event, 
                           WebCursor* cursor);
  virtual NPObject* GetPluginScriptableObject();
  virtual void DidFinishLoadWithReason(NPReason reason);
  virtual int GetProcessId();
  virtual HWND GetWindowHandle();

  virtual void FlushGeometryUpdates() {
  }
  virtual void SendJavaScriptStream(const std::string& url, 
                                    const std::wstring& result, 
                                    bool success, bool notify_needed, 
                                    int notify_data);
  virtual void DidReceiveManualResponse(const std::string& url,
                                        const std::string& mime_type,
                                        const std::string& headers,
                                        uint32 expected_length,
                                        uint32 last_modified);
  virtual void DidReceiveManualData(const char* buffer, int length);
  virtual void DidFinishManualLoading();
  virtual void DidManualLoadFail();
  virtual std::wstring GetPluginPath();
  virtual void InstallMissingPlugin();
  virtual WebPluginResourceClient* CreateResourceClient(int resource_id,
                                                        const std::string &url,
                                                        bool notify_needed,
                                                        void *notify_data);

  virtual void URLRequestRouted(const std::string&url, bool notify_needed,
                                void* notify_data);
  bool windowless() const {
    return windowless_;
  }

  enum PluginQuirks {
    PLUGIN_QUIRK_SETWINDOW_TWICE = 1,
    PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE = 2,
    PLUGIN_QUIRK_DONT_CALL_WND_PROC_RECURSIVELY = 4,
    PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY = 8,
    PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES = 16,
  };

  int quirks() { return quirks_; }

  static void MoveWindow(HWND window,
                         const gfx::Rect& window_rect,
                         const gfx::Rect& clip_rect,
                         bool visible);

 private:
  WebPluginDelegateImpl(HWND containing_window,
                        NPAPI::PluginInstance *instance);
  ~WebPluginDelegateImpl();

  //--------------------------
  // used for windowed plugins
  void WindowedUpdateGeometry(const gfx::Rect& window_rect,
                              const gfx::Rect& clip_rect, bool visible);
  // Create the native window. 
  // Returns true if the window is created (or already exists).
  // Returns false if unable to create the window.
  bool WindowedCreatePlugin();

  // Destroy the native window.
  void WindowedDestroyWindow();

  // Reposition the native window to be in sync with the given geometry.
  // Returns true if the native window has moved or been clipped differently.
  bool WindowedReposition(const gfx::Rect& window_rect,
                          const gfx::Rect& clip_rect, bool visible);

  // Tells the plugin about the current state of the window.
  // See NPAPI NPP_SetWindow for more information.
  void WindowedSetWindow();

  // Registers the window class for our window
  ATOM RegisterNativeWindowClass();

  // Our WndProc functions.
  static LRESULT CALLBACK NativeWndProc(
      HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
  static LRESULT CALLBACK FlashWindowlessWndProc(
      HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);

  // Used for throttling Flash messages.
  static void ClearThrottleQueueForWindow(HWND window);
  static void OnThrottleMessage();
  static void ThrottleMessage(WNDPROC proc, HWND hwnd, UINT message,
      WPARAM wParam, LPARAM lParam);

  //----------------------------
  // used for windowless plugins
  void WindowlessUpdateGeometry(const gfx::Rect& window_rect,
                                const gfx::Rect& clip_rect);
  void WindowlessPaint(HDC hdc, const gfx::Rect& rect);

  // Tells the plugin about the current state of the window.
  // See NPAPI NPP_SetWindow for more information.
  void WindowlessSetWindow(bool force_set_window);


  //-----------------------------------------
  // used for windowed and windowless plugins

  NPAPI::PluginInstance* instance() { return instance_.get(); }

  // Closes down and destroys our plugin instance.
  void DestroyInstance();

  // Returns the cursor type.
  // TODO(iyengar) Add support for custom cursors.
  WebCursor::Type GetCursorType(HCURSOR cursor) const;

  // used for windowed plugins
  HWND windowed_handle_;
  bool windowed_did_set_window_;
  gfx::Rect windowed_last_pos_;

  // this is an optimization to avoid calling SetWindow to the plugin 
  // when it is not necessary.  Initially, we need to call SetWindow,
  // and after that we only need to call it when the geometry changes.
  // use this flag to indicate whether we really need it or not.
  bool windowless_needs_set_window_;

  // used by windowed and windowless plugins
  bool windowless_;

  WebPlugin* plugin_;
  scoped_refptr<NPAPI::PluginInstance> instance_;

  // Original wndproc before we subclassed.
  WNDPROC plugin_wnd_proc_;

  // Used to throttle WM_USER+1 messages in Flash.
  uint32 last_message_;
  bool is_calling_wndproc;

  HWND parent_;
  NPWindow window_;
  gfx::Rect window_rect_;
  gfx::Rect clip_rect_;
  int quirks_;

  // We only move/size the plugin window once after its creation. The
  // rest of the moves are controlled by the browser. This flag controls
  // this behaviour.
  bool initial_plugin_resize_done_;

  // Windowless plugins don't have keyboard focus causing issues with the
  // plugin not receiving keyboard events if the plugin enters a modal 
  // loop like TrackPopupMenuEx or MessageBox, etc.
  // This is a basic issue with windows activation and focus arising due to
  // the fact that these windows are created by different threads. Activation
  // and focus are thread specific states, and if the browser has focus,
  // the plugin may not have focus. 
  // To fix a majority of these activation issues we create a dummy visible 
  // child window to which we set focus whenever the windowless plugin 
  // receives a WM_LBUTTONDOWN/WM_RBUTTONDOWN message via NPP_HandleEvent.
  HWND dummy_window_for_activation_;
  bool CreateDummyWindowForActivation();

  static std::list<MSG> throttle_queue_;

  // Returns true if the event passed in needs to be tracked for a potential
  // modal loop.
  static bool ShouldTrackEventForModalLoops(NPEvent* event);

  // The message filter hook procedure, which tracks modal loops entered by
  // a plugin in the course of a NPP_HandleEvent call.
  static LRESULT CALLBACK HandleEventMessageFilterHook(int code, WPARAM wParam,
                                                       LPARAM lParam);

  // Called by the message filter hook when the plugin enters a modal loop.
  void OnModalLoopEntered();

  // Returns true if the message passed in corresponds to a user gesture.
  static bool IsUserGestureMessage(unsigned int message);

  // Indicates the end of a user gesture period.
  void OnUserGestureEnd();

  // Handle to the message filter hook
  HHOOK handle_event_message_filter_hook_;

  // The current instance of the plugin which entered the modal loop.
  static WebPluginDelegateImpl* current_plugin_instance_;

  // Event which is set when the plugin enters a modal loop in the course
  // of a NPP_HandleEvent call.
  HANDLE handle_event_pump_messages_event_;

  // Holds the depth of the HandleEvent callstack.
  int handle_event_depth_;

  // This flag indicates whether we started tracking a user gesture message.
  bool user_gesture_message_posted_;

  // Runnable Method Factory used to invoke the OnUserGestureEnd method
  // asynchronously.
  ScopedRunnableMethodFactory<WebPluginDelegateImpl> user_gesture_msg_factory_;

  // The url with which the plugin was instantiated.
  std::string plugin_url_;

  // Indicates if the download would be initiated by the plugin or us.
  bool load_manually_;

  // Indicates whether a geometry update sequence is the first.
  bool first_geometry_update_;

  DISALLOW_EVIL_CONSTRUCTORS(WebPluginDelegateImpl);
};

#endif  // #ifndef WEBKIT_GLUE_PLUGIN_WEBPLUGIN_DELEGATE_IMPL_H__