Home | History | Annotate | Download | only in npapi
      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 
     16 namespace content {
     17 
     18 class 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 //
     69 class 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