summaryrefslogtreecommitdiffstats
path: root/chrome_frame/chrome_frame_npapi.h
blob: 5101592d6f95ebb99eef6fde44203b234288b97d (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
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_FRAME_CHROME_FRAME_NPAPI_H_
#define CHROME_FRAME_CHROME_FRAME_NPAPI_H_

#include <atlbase.h>
#include <atlwin.h>
#include <string>

#include "chrome_frame/chrome_frame_automation.h"
#include "chrome_frame/chrome_frame_plugin.h"
#include "chrome_frame/np_browser_functions.h"
#include "chrome_frame/np_event_listener.h"
#include "chrome_frame/np_proxy_service.h"
#include "chrome_frame/npapi_url_request.h"

class MessageLoop;
class nsICookieService;
class nsIURI;

// ChromeFrameNPAPI: Implementation of the NPAPI plugin, which is responsible
// for hosting a chrome frame, i.e. an iframe like widget which hosts the the
// chrome window. This object delegates to Chrome.exe  (via the Chrome
// IPC-based automation mechanism) for the actual rendering.
class ChromeFrameNPAPI
    : public CWindowImpl<ChromeFrameNPAPI>,
      public ChromeFramePlugin<ChromeFrameNPAPI>,
      public NpEventDelegate {
 public:
  typedef ChromeFramePlugin<ChromeFrameNPAPI> Base;

  // NPObject structure which is exposed by us.
  struct ChromeFrameNPObject : public NPObject {
    NPP npp;
    ChromeFrameNPAPI* chrome_frame_plugin_instance;
  };

  typedef enum {
    PLUGIN_PROPERTY_VERSION,
    PLUGIN_PROPERTY_SRC,
    PLUGIN_PROPERTY_ONLOAD,
    PLUGIN_PROPERTY_ONERROR,
    PLUGIN_PROPERTY_ONMESSAGE,
    PLUGIN_PROPERTY_READYSTATE,
    PLUGIN_PROPERTY_ONPRIVATEMESSAGE,
    PLUGIN_PROPERTY_USECHROMENETWORK,
    PLUGIN_PROPERTY_ONCLOSE,
    PLUGIN_PROPERTY_COUNT  // must be last
  } PluginPropertyId;

  static const int kWmSwitchFocusToChromeFrame = WM_APP + 0x100;

  static NPClass plugin_class_;
  static NPClass* PluginClass() {
    return &plugin_class_;
  }

  ChromeFrameNPAPI();
  ~ChromeFrameNPAPI();

  bool Initialize(NPMIMEType mime_type, NPP instance, uint16 mode,
                  int16 argc, char* argn[], char* argv[]);
  void Uninitialize();

  bool SetWindow(NPWindow* window_info);
  void UrlNotify(const char* url, NPReason reason, void* notify_data);
  NPError NewStream(NPMIMEType type, NPStream* stream, NPBool seekable,
                    uint16* stream_type);
  int32 WriteReady(NPStream* stream);
  int32 Write(NPStream* stream, int32 offset, int32 len, void* buffer);
  NPError DestroyStream(NPStream* stream, NPReason reason);

  void Print(NPPrint* print_info);

  // NPObject functions, which ensure that the plugin object is scriptable.
  static bool HasMethod(NPObject* obj, NPIdentifier name);
  static bool Invoke(NPObject* header, NPIdentifier name,
                     const NPVariant* args, uint32_t arg_count,
                     NPVariant* result);
  static NPObject* AllocateObject(NPP instance, NPClass* class_name);
  static void DeallocateObject(NPObject* header);

  // Called by the scripting environment when the native code is shutdown.
  // Any attempt to message a NPObject instance after the invalidate callback
  // has been called will result in undefined behavior, even if the native code
  // is still retaining those NPObject instances.
  static void Invalidate(NPObject* header);

  // The following functions need to be implemented to ensure that FF3
  // invokes methods on the plugin. If these methods are not implemented
  // then invokes on the plugin NPObject from the script fail with a
  // bad NPObject error.
  static bool HasProperty(NPObject* obj, NPIdentifier name);
  static bool GetProperty(NPObject* obj, NPIdentifier name, NPVariant *variant);
  static bool SetProperty(NPObject* obj, NPIdentifier name,
                          const NPVariant *variant);

  // Returns the ChromeFrameNPAPI object pointer from the NPP instance structure
  // passed in by the browser.
  static ChromeFrameNPAPI* ChromeFrameInstanceFromPluginInstance(NPP instance);

  // Returns the ChromeFrameNPAPI object pointer from the NPObject structure
  // which represents our plugin class.
  static ChromeFrameNPAPI* ChromeFrameInstanceFromNPObject(void* object);

BEGIN_MSG_MAP(ChromeFrameNPAPI)
  MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
  CHAIN_MSG_MAP(Base)
END_MSG_MAP()

  LRESULT OnSetFocus(UINT message, WPARAM wparam, LPARAM lparam,
                     BOOL& handled);  // NO_LINT

  // Implementation of NpEventDelegate
  virtual void OnEvent(const char* event_name);

  void OnFocus();
  void OnBlur();

  // Implementation of SetProperty, public to allow unittesting.
  bool SetProperty(NPIdentifier name, const NPVariant *variant);
  // Implementation of GetProperty, public to allow unittesting.
  bool GetProperty(NPIdentifier name, NPVariant *variant);

  // Initialize string->identifier mapping, public to allow unittesting.
  static void InitializeIdentifiers();

  bool PreProcessContextMenu(HMENU menu);
  bool HandleContextMenuCommand(UINT cmd, const IPC::ContextMenuParams& params);
 protected:
  // Handler for accelerator messages passed on from the hosted chrome
  // instance.
  virtual void OnAcceleratorPressed(int tab_handle, const MSG& accel_message);
  virtual void OnTabbedOut(int tab_handle, bool reverse);
  virtual void OnOpenURL(int tab_handle, const GURL& url,
                         const GURL& referrer, int open_disposition);
  virtual void OnLoad(int tab_handle, const GURL& url);
  virtual void OnMessageFromChromeFrame(int tab_handle,
                                        const std::string& message,
                                        const std::string& origin,
                                        const std::string& target);
  // ChromeFrameDelegate overrides
  virtual void OnLoadFailed(int error_code, const std::string& url);
  virtual void OnAutomationServerReady();
  virtual void OnAutomationServerLaunchFailed(
      AutomationLaunchResult reason, const std::string& server_version);
  virtual void OnExtensionInstalled(const FilePath& path,
      void* user_data, AutomationMsg_ExtensionResponseValues response);
  virtual void OnGetEnabledExtensionsComplete(
      void* user_data,
      const std::vector<FilePath>& extension_directories);
  virtual void OnCloseTab(int tab_handle);

 private:
  void SubscribeToFocusEvents();
  void UnsubscribeFromFocusEvents();

  // Equivalent of:
  // event = window.document.createEvent("Event");
  // event.initEvent(type, bubbles, cancelable);
  // and then returns the event object.
  bool CreateEvent(const std::string& type, bool bubbles, bool cancelable,
                   NPObject** basic_event);

  // Creates and initializes an event object of type "message".
  // Used for postMessage.
  bool CreateMessageEvent(bool bubbles, bool cancelable,
      const std::string& data, const std::string& origin,
      NPObject** message_event);

  // Calls chrome_frame.dispatchEvent to fire events to event listeners.
  void DispatchEvent(NPObject* event);

  // Returns a pointer to the <object> element in the page that
  // hosts the plugin.  Note that this is the parent element of the <embed>
  // element.  The <embed> element doesn't support some of the events that
  // we require, so we use the object element for receiving events.
  bool GetObjectElement(nsIDOMElement** element);

  // Prototype for all methods that can be invoked from script.
  typedef bool (ChromeFrameNPAPI::*PluginMethod)(NPObject* npobject,
                                                 const NPVariant* args,
                                                 uint32_t arg_count,
                                                 NPVariant* result);

  // Implementations of scriptable methods.

  bool NavigateToURL(const NPVariant* args, uint32_t arg_count,
                     NPVariant* result);

  bool postMessage(NPObject* npobject, const NPVariant* args,
                   uint32_t arg_count, NPVariant* result);

  // This method is only available when the control is in privileged mode.
  bool postPrivateMessage(NPObject* npobject, const NPVariant* args,
                          uint32_t arg_count, NPVariant* result);

  // This method is only available when the control is in privileged mode.
  bool installExtension(NPObject* npobject, const NPVariant* args,
                        uint32_t arg_count, NPVariant* result);

  // This method is only available when the control is in privileged mode.
  bool loadExtension(NPObject* npobject, const NPVariant* args,
                     uint32_t arg_count, NPVariant* result);

  // This method is only available when the control is in privileged mode.
  bool enableExtensionAutomation(NPObject* npobject, const NPVariant* args,
                                 uint32_t arg_count, NPVariant* result);

  // This method is only available when the control is in privileged mode.
  bool getEnabledExtensions(NPObject* npobject, const NPVariant* args,
                            uint32_t arg_count, NPVariant* result);

  // Pointers to method implementations.
  static PluginMethod plugin_methods_[];

  // NPObject method ids exposed by the plugin.
  static NPIdentifier plugin_method_identifiers_[];

  // NPObject method names exposed by the plugin.
  static const NPUTF8* plugin_method_identifier_names_[];

  // NPObject property ids exposed by the plugin.
  static NPIdentifier plugin_property_identifiers_[];

  // NPObject property names exposed by the plugin.
  static const NPUTF8*
      plugin_property_identifier_names_[];

  virtual void OnFinalMessage(HWND window);

  // Helper function to invoke a function on a NPObject.
  bool InvokeDefault(NPObject* object, const std::string& param,
                     NPVariant* result);

  bool InvokeDefault(NPObject* object, const NPVariant& param,
                     NPVariant* result);

  bool InvokeDefault(NPObject* object, unsigned param_count,
                     const NPVariant* params, NPVariant* result);

  // Helper function to convert javascript code to a NPObject we can
  // invoke on.
  virtual NPObject* JavascriptToNPObject(const std::string& function_name);

  // Helper function to execute a script.
  // Returns S_OK on success.
  bool ExecuteScript(const std::string& script, NPVariant* result);

  // Returns true if the script passed in is a valid function in the DOM.
  bool IsValidJavascriptFunction(const std::string& script);

  // Converts the data parameter to an NPVariant and forwards the call to the
  // other FireEvent method.
  void FireEvent(const std::string& event_type, const std::string& data);

  // Creates an event object, assigns the data parameter to a |data| property
  // on the event object and then calls DispatchEvent to fire the event to
  // listeners.  event_type is the name of the event being fired.
  void FireEvent(const std::string& event_type, const NPVariant& data);

  // Returns a new prefs service. Virtual to allow overriding in unittests.
  virtual NpProxyService* CreatePrefService();

  // Returns our associated windows' location.
  virtual std::string GetLocation();

  // Returns true iff we're successfully able to query for the browser's
  // incognito mode, and the browser returns true.
  virtual bool GetBrowserIncognitoMode();

  // Returns the window script object for the page.
  // This function will cache the window object to avoid calling
  // npapi::GetValue which can cause problems in Opera.
  NPObject* GetWindowObject() const;

  virtual void SetReadyState(READYSTATE new_state) {
    ready_state_ = new_state;
    NPVariant var;
    INT32_TO_NPVARIANT(ready_state_, var);
    FireEvent("readystatechanged", var);
  }

  // Host function to compile-time asserts over members of this class.
  static void CompileAsserts();

  static LRESULT CALLBACK DropKillFocusHook(int code, WPARAM wparam,
                                            LPARAM lparam);  // NO_LINT

  // The plugins opaque instance handle
  NPP instance_;

  // The plugin instantiation mode (NP_FULL or NP_EMBED)
  int16 mode_;
  // The plugins mime type.
  std::string mime_type_;

  // Set to true if we need a full page plugin.
  bool force_full_page_plugin_;

  scoped_refptr<NpProxyService> pref_service_;

  // Used to receive focus and blur events from the object element
  // that hosts the plugin.
  scoped_refptr<NpEventListener> focus_listener_;

  // In some cases the IPC channel proxy object is instantiated on the UI
  // thread in FF. It then tries to use the IPC logger, which relies on
  // the message loop being around. Declaring a dummy message loop
  // is a hack to get around this. Eventually the automation code needs to
  // be fixed to ensure that the channel proxy always gets created on a thread
  // with a message loop.
  static MessageLoop* message_loop_;
  static int instance_count_;

  // The following members contain the NPObject pointers representing the
  // onload/onerror/onmessage handlers on the page.
  ScopedNpObject<NPObject> onerror_handler_;
  ScopedNpObject<NPObject> onmessage_handler_;
  ScopedNpObject<NPObject> onprivatemessage_handler_;
  ScopedNpObject<NPObject> onclose_handler_;

  // As a workaround for a problem in Opera we cache the window object.
  // The problem stems from two things: window messages aren't always removed
  // from the message queue and messages can be pumped inside GetValue.
  // This can cause an infinite recursion of processing the same message
  // repeatedly.
  mutable ScopedNpObject<NPObject> window_object_;

  // Note since 'onload' is a registered event name, the browser will
  // automagically create a code block for the handling code and hook it
  // up to the CF object via addEventListener.
  // See this list of known event types:
  // http://www.w3.org/TR/DOM-Level-3-Events/events.html#Event-types

  READYSTATE ready_state_;


  // Popups are enabled
  bool enabled_popups_;

  // The value of src property keeping the current URL.
  std::string src_;
  // Used to fetch network resources when host network stack is in use.
  NPAPIUrlRequestManager url_fetcher_;

  // Set if we receive a navigation request before initializing Chrome.
  bool navigate_after_initialization_;
};

#endif  // CHROME_FRAME_CHROME_FRAME_NPAPI_H_