1// Copyright (c) 2011 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#ifndef CONTENT_CHILD_NPAPI_WEBPLUGIN_IME_WIN_H_
6#define CONTENT_CHILD_NPAPI_WEBPLUGIN_IME_WIN_H_
7
8#include <string>
9#include <vector>
10
11#include "base/basictypes.h"
12#include "base/strings/string16.h"
13#include "third_party/npapi/bindings/npapi.h"
14#include "ui/gfx/rect.h"
15
16namespace content {
17
18class PluginInstance;
19
20// A class that emulates an IME for windowless plug-ins. A windowless plug-in
21// does not have a window. Therefore, we cannot attach an IME to a windowless
22// plug-in. To allow such windowless plug-ins to use IMEs without any changes to
23// them, this class receives the IME data from a browser and patches IMM32
24// functions to return the IME data when a windowless plug-in calls IMM32
25// functions. I would not Flash retrieves pointers to IMM32 functions with
26// GetProcAddress(), this class also needs a hook to GetProcAddress() to
27// dispatch IMM32 function calls from a plug-in to this class as listed in the
28// following snippet.
29//
30//   FARPROC WINAPI GetProcAddressPatch(HMODULE module, LPCSTR name) {
31//     FARPROC* proc = WebPluginIMEWin::GetProcAddress(name);
32//     if (proc)
33//       return proc;
34//     return ::GetProcAddress(module, name);
35//   }
36//   ...
37//   app::win::IATPatchFunction get_proc_address;
38//   get_proc_address.Patch(
39//       GetPluginPath().value().c_str(), "kernel32.dll", "GetProcAddress",
40//       GetProcAddressPatch);
41//
42// After we successfuly dispatch IMM32 calls from a plug-in to this class, we
43// need to update its IME data so the class can return it to the plug-in through
44// its IMM32 calls. To update the IME data, we call CompositionUpdated() or
45// CompositionCompleted() BEFORE sending an IMM32 Window message to the plugin
46// with a SendEvents() call as listed in the following snippet. (Plug-ins call
47// IMM32 functions when it receives IMM32 window messages. We need to update the
48// IME data of this class before sending IMM32 messages so the plug-ins can get
49// the latest data.)
50//
51//   WebPluginIMEWin ime;
52//   ...
53//   base::string16 text = "composing";
54//   std::vector<int> clauses;
55//   clauses.push_back(0);
56//   clauses.push_back(text.length());
57//   std::vector<int> target;
58//   ime.CompositionUpdated(text, clauses, target, text.length());
59//   ime.SendEvents(instance());
60//
61//   base::string16 result = "result";
62//   ime.CompositionCompleted(result);
63//   ime.SendEvents(instance());
64//
65// This class also provides GetStatus() so we can retrieve the IME status
66// changed by a plug-in with IMM32 functions. This function is mainly used for
67// retrieving the position of a caret.
68//
69class WebPluginIMEWin {
70 public:
71  // A simple class that allows a plug-in to access a WebPluginIMEWin instance
72  // only in a scope.
73  class ScopedLock {
74   public:
75    explicit ScopedLock(WebPluginIMEWin* instance) : instance_(instance) {
76      if (instance_)
77        instance_->Lock();
78    }
79    ~ScopedLock() {
80      if (instance_)
81        instance_->Unlock();
82    }
83
84   private:
85    WebPluginIMEWin* instance_;
86  };
87
88  WebPluginIMEWin();
89  ~WebPluginIMEWin();
90
91  // Sends raw IME events sent from a browser to this IME emulator and updates
92  // the list of Windows events to be sent to a plug-in. A raw IME event is
93  // mapped to two or more Windows events and it is not so trivial to send these
94  // Windows events to a plug-in. This function inserts Windows events in the
95  // order expected by a plug-in.
96  void CompositionUpdated(const base::string16& text,
97                          std::vector<int> clauses,
98                          std::vector<int> target,
99                          int cursor_position);
100  void CompositionCompleted(const base::string16& text);
101
102  // Send all the events added in Update() to a plug-in.
103  bool SendEvents(PluginInstance* instance);
104
105  // Retrieves the status of this IME emulator.
106  bool GetStatus(int* input_type, gfx::Rect* caret_rect);
107
108  // Returns the pointers to IMM32-emulation functions implemented by this
109  // class. This function is used for over-writing the ones returned from
110  // GetProcAddress() calls of Win32 API.
111  static FARPROC GetProcAddress(const char* name);
112
113 private:
114  // Allow (or disallow) the patch functions to use this WebPluginIMEWin
115  // instance through our patch functions. Our patch functions need a static
116  // member variable |instance_| to access a WebPluginIMEWIn instance. We lock
117  // this static variable to prevent two or more plug-ins from accessing a
118  // WebPluginIMEWin instance.
119  void Lock();
120  void Unlock();
121
122  // Retrieve the instance of this class.
123  static WebPluginIMEWin* GetInstance(HIMC context);
124
125  // IMM32 patch functions implemented by this class.
126  static BOOL WINAPI ImmAssociateContextEx(HWND window,
127                                           HIMC context,
128                                           DWORD flags);
129  static LONG WINAPI ImmGetCompositionStringW(HIMC context,
130                                              DWORD index,
131                                              LPVOID dst_data,
132                                              DWORD dst_size);
133  static HIMC WINAPI ImmGetContext(HWND window);
134  static BOOL WINAPI ImmReleaseContext(HWND window, HIMC context);
135  static BOOL WINAPI ImmSetCandidateWindow(HIMC context,
136                                           CANDIDATEFORM* candidate);
137  static BOOL WINAPI ImmSetOpenStatus(HIMC context, BOOL open);
138
139  // a list of NPEvents to be sent to a plug-in.
140  std::vector<NPEvent> events_;
141
142  // The return value for GCS_COMPSTR.
143  base::string16 composition_text_;
144
145  // The return value for GCS_RESULTSTR.
146  base::string16 result_text_;
147
148  // The return value for GCS_COMPATTR.
149  std::string composition_attributes_;
150
151  // The return value for GCS_COMPCLAUSE.
152  std::vector<uint32> composition_clauses_;
153
154  // The return value for GCS_RESULTCLAUSE.
155  uint32 result_clauses_[2];
156
157  // The return value for GCS_CURSORPOS.
158  int cursor_position_;
159
160  // The return value for GCS_DELTASTART.
161  int delta_start_;
162
163  // Whether we are composing text. This variable is used for sending a
164  // WM_IME_STARTCOMPOSITION message when we start composing IME text.
165  bool composing_text_;
166
167  // Whether a plug-in supports IME messages. When a plug-in cannot handle
168  // IME messages, we need to send the IME text with WM_CHAR messages as Windows
169  // does.
170  bool support_ime_messages_;
171
172  // The IME status received from a plug-in.
173  bool status_updated_;
174  int input_type_;
175  gfx::Rect caret_rect_;
176
177  // The pointer to the WebPluginIMEWin instance used by patch functions.
178  static WebPluginIMEWin* instance_;
179};
180
181}  // namespace content
182
183#endif  // CONTENT_CHILD_NPAPI_WEBPLUGIN_IME_WIN_H_
184