1 // Copyright 2010-2018, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //     * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 //     * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30 // Session class of Mozc server.
31 
32 #ifndef MOZC_SESSION_SESSION_H_
33 #define MOZC_SESSION_SESSION_H_
34 
35 #include <memory>
36 #include <string>
37 
38 #include "base/port.h"
39 #include "composer/composer.h"
40 #include "session/session_interface.h"
41 // for FRIEND_TEST()
42 #include "testing/base/public/gunit_prod.h"
43 #include "transliteration/transliteration.h"
44 
45 namespace mozc {
46 namespace commands {
47 class ApplicationInfo;
48 class Capability;
49 class Command;
50 class Input;
51 class KeyEvent;
52 }  // namespace commands
53 
54 namespace composer {
55 class Table;
56 }  // namespace composer
57 
58 class EngineInterface;
59 
60 namespace session {
61 class ImeContext;
62 
63 class Session : public SessionInterface {
64  public:
65   explicit Session(EngineInterface *engine);
66   virtual ~Session();
67 
68   virtual bool SendKey(mozc::commands::Command *command);
69 
70   // Check if the input key event will be consumed by the session.
71   virtual bool TestSendKey(mozc::commands::Command *command);
72 
73   // Perform the SEND_COMMAND command defined commands.proto.
74   virtual bool SendCommand(mozc::commands::Command *command);
75 
76   // Turn on IME. Do nothing (but the keyevent is consumed) when IME is already
77   // turned on.
78   bool IMEOn(mozc::commands::Command *command);
79 
80   // Turn off IME. Do nothing (but the keyevent is consumed) when IME is already
81   // turned off.
82   bool IMEOff(mozc::commands::Command *command);
83 
84   // Unlike IMEOn/IMEOff, these commands 1) can update compositioin mode, and
85   // 2) are functional even when IME is already turned on/off.
86   // TODO(team): Merge these into IMEOn/Off once b/10250883 is fixed.
87   bool MakeSureIMEOn(mozc::commands::Command *command);
88   bool MakeSureIMEOff(mozc::commands::Command *command);
89 
90   bool EchoBack(mozc::commands::Command *command);
91   bool EchoBackAndClearUndoContext(mozc::commands::Command *command);
92   bool DoNothing(mozc::commands::Command *command);
93 
94   // Tries deleting the focused candidate from the user prediction history. If
95   // that candidate, as a key value pair, doesn't exist in the user history,
96   // nothing happens. Regardless of the result of internal history deletion,
97   // invoking this method has the same effect as ConvertCancel() from the
98   // viewpoint of session, meaning that the session state gets back to
99   // composition.
100   bool DeleteSelectedCandidateFromHistory(mozc::commands::Command *command);
101 
102   // Resets the composer and clear conversion segments.
103   // History segments will not be cleared.
104   // Therefore if a user commits "風"(かぜ) and Revert method is called,
105   // preedit "ひいた"  will be converted into "邪引いた".
106   bool Revert(mozc::commands::Command *command);
107   // Reset the composer and clear all the segments (including history segments).
108   // Therefore preedit "ひいた"  will *not* be converted into "邪引いた"
109   // on the situation described above.
110   bool ResetContext(mozc::commands::Command *command);
111 
112   // Returns the current status such as a composition string, input mode, etc.
113   bool GetStatus(mozc::commands::Command *command);
114 
115   // Fills Output::Callback with the CONVERT_REVERSE SessionCommand to
116   // ask the client to send back the SessionCommand to the server.
117   // This function is called when the key event representing the
118   // ConvertReverse keybinding is called.
119   bool RequestConvertReverse(mozc::commands::Command *command);
120 
121   // Begins reverse conversion for the given session.  This function
122   // is called when the CONVERT_REVERSE SessionCommand is called.
123   bool ConvertReverse(mozc::commands::Command *command);
124 
125   // Fills Output::Callback with the Undo SessionCommand to ask the
126   // client to send back the SessionCommand to the server.
127   // This function is called when the key event representing the
128   // Undo keybinding is called.
129   bool RequestUndo(mozc::commands::Command *command);
130 
131   // Undos the commitment.  This function is called when the
132   // UNDO SessionCommand is called.
133   bool Undo(mozc::commands::Command *command);
134 
135   bool InsertSpace(mozc::commands::Command *command);
136   bool InsertSpaceToggled(mozc::commands::Command *command);
137   bool InsertSpaceHalfWidth(mozc::commands::Command *command);
138   bool InsertSpaceFullWidth(mozc::commands::Command *command);
139   bool InsertCharacter(mozc::commands::Command *command);
140   bool Delete(mozc::commands::Command *command);
141   bool Backspace(mozc::commands::Command *command);
142   bool EditCancel(mozc::commands::Command *command);
143   bool EditCancelAndIMEOff(mozc::commands::Command *command);
144 
145   bool MoveCursorRight(mozc::commands::Command *command);
146   bool MoveCursorLeft(mozc::commands::Command *command);
147   bool MoveCursorToEnd(mozc::commands::Command *command);
148   bool MoveCursorToBeginning(mozc::commands::Command *command);
149   bool MoveCursorTo(mozc::commands::Command *command);
150   bool Convert(mozc::commands::Command *command);
151   // Starts conversion not using user history.  This is used for debugging.
152   bool ConvertWithoutHistory(mozc::commands::Command *command);
153   bool ConvertNext(mozc::commands::Command *command);
154   bool ConvertPrev(mozc::commands::Command *command);
155   // Shows the next page of candidates.
156   bool ConvertNextPage(mozc::commands::Command *command);
157   // Shows the previous page of candidates.
158   bool ConvertPrevPage(mozc::commands::Command *command);
159   bool ConvertCancel(mozc::commands::Command *command);
160   bool PredictAndConvert(mozc::commands::Command *command);
161   // Note: Commit() also triggers zero query suggestion.
162   // TODO(team): Rename this method to CommitWithZeroQuerySuggest.
163   bool Commit(mozc::commands::Command *command);
164   bool CommitNotTriggeringZeroQuerySuggest(commands::Command *command);
165   bool CommitFirstSuggestion(mozc::commands::Command *command);
166   // Select a candidate located by input.command.id and commit.
167   bool CommitCandidate(mozc::commands::Command *command);
168 
169   // Expands suggestion candidates.
170   bool ExpandSuggestion(mozc::commands::Command *command);
171 
172   // Commits only the first segment.
173   bool CommitSegment(mozc::commands::Command *command);
174   // Commits some characters at the head of the preedit.
175   bool CommitHead(size_t count, mozc::commands::Command *command);
176   // Commits preedit if in password mode.
177   bool CommitIfPassword(mozc::commands::Command *command);
178 
179   bool SegmentFocusRight(mozc::commands::Command *command);
180   bool SegmentFocusLeft(mozc::commands::Command *command);
181   bool SegmentFocusLast(mozc::commands::Command *command);
182   bool SegmentFocusLeftEdge(mozc::commands::Command *command);
183   bool SegmentWidthExpand(mozc::commands::Command *command);
184   bool SegmentWidthShrink(mozc::commands::Command *command);
185 
186   // Selects the transliteration candidate.  If the current state is
187   // composition, candidates will be generated with only translitaration
188   // candidates.
189   bool ConvertToHiragana(mozc::commands::Command *command);
190   bool ConvertToFullKatakana(mozc::commands::Command *command);
191   bool ConvertToHalfKatakana(mozc::commands::Command *command);
192   bool ConvertToFullASCII(mozc::commands::Command *command);
193   bool ConvertToHalfASCII(mozc::commands::Command *command);
194   bool ConvertToHalfWidth(mozc::commands::Command *command);
195   // Switch the composition to Hiragana, full-width Katakana or
196   // half-width Katakana by rotation.
197   bool SwitchKanaType(mozc::commands::Command *command);
198 
199   // Select the transliteration candidate if the current status is
200   // conversion.  This is same with the above ConvertTo functions.  If
201   // the current state is composition, the display mode is changed to the
202   // transliteration and the composition state still remains.
203   bool DisplayAsHiragana(mozc::commands::Command *command);
204   bool DisplayAsFullKatakana(mozc::commands::Command *command);
205   bool DisplayAsHalfKatakana(mozc::commands::Command *command);
206   bool TranslateFullASCII(mozc::commands::Command *command);
207   bool TranslateHalfASCII(mozc::commands::Command *command);
208   bool TranslateHalfWidth(mozc::commands::Command *command);
209   bool ToggleAlphanumericMode(mozc::commands::Command *command);
210 
211   // Switch the input mode.
212   bool InputModeHiragana(mozc::commands::Command *command);
213   bool InputModeFullKatakana(mozc::commands::Command *command);
214   bool InputModeHalfKatakana(mozc::commands::Command *command);
215   bool InputModeFullASCII(mozc::commands::Command *command);
216   bool InputModeHalfASCII(mozc::commands::Command *command);
217   bool InputModeSwitchKanaType(mozc::commands::Command *command);
218 
219   // Specify the input field type.
220   bool SwitchInputFieldType(mozc::commands::Command *command);
221 
222   // Let client launch config dialog
223   bool LaunchConfigDialog(mozc::commands::Command *command);
224 
225   // Let client launch dictionary tool
226   bool LaunchDictionaryTool(mozc::commands::Command *command);
227 
228   // Let client launch word register dialog
229   bool LaunchWordRegisterDialog(mozc::commands::Command *command);
230 
231   // Undo if pre-composition is empty. Rewind KANA cycle othrewise.
232   bool UndoOrRewind(mozc::commands::Command *command);
233   // Send a command to the composer to append a special string.
234   bool SendComposerCommand(
235       const mozc::composer::Composer::InternalCommand composer_command,
236       mozc::commands::Command *command);
237 
238   bool ReportBug(mozc::commands::Command *command);
239 
240   virtual void SetConfig(mozc::config::Config *config);
241 
242   virtual void SetRequest(const mozc::commands::Request *request);
243 
244   virtual void SetTable(const mozc::composer::Table *table);
245 
246   // Set client capability for this session.  Used by unittest.
247   virtual void set_client_capability(
248       const mozc::commands::Capability &capability);
249 
250   // Set application information for this session.
251   virtual void set_application_info(
252       const mozc::commands::ApplicationInfo &application_info);
253 
254   // Get application information
255   virtual const mozc::commands::ApplicationInfo &application_info() const;
256 
257   // Return the time when this instance was created.
258   virtual uint64 create_session_time() const;
259 
260   // return 0 (default value) if no command is executed in this session.
261   virtual uint64 last_command_time() const;
262 
263   // TODO(komatsu): delete this funciton.
264   // For unittest only
265   mozc::composer::Composer *get_internal_composer_only_for_unittest();
266 
267   const ImeContext &context() const;
268 
269  private:
270   FRIEND_TEST(SessionTest, OutputInitialComposition);
271   FRIEND_TEST(SessionTest, IsFullWidthInsertSpace);
272   FRIEND_TEST(SessionTest, RequestUndo);
273 
274   // Underlying conversion engine for this session. Please note that:
275   //   i) Session doesn't own the pointer.
276   //  ii) The state of underlying converter will change because it manages user
277   //      history, user dictionary, etc.
278   mozc::EngineInterface *engine_;
279 
280   std::unique_ptr<ImeContext> context_;
281   std::unique_ptr<ImeContext> prev_context_;
282 
283   void InitContext(ImeContext *context) const;
284 
285   void PushUndoContext();
286   void PopUndoContext();
287   void ClearUndoContext();
288 
289   // Return true if full width space is preferred in the given new input
290   // state than half width space. When |input| does not have new input mode,
291   // the current mode will be considered.
292   bool IsFullWidthInsertSpace(const mozc::commands::Input &input) const;
293 
294   bool EditCancelOnPasswordField(mozc::commands::Command *command);
295 
296   bool ConvertToTransliteration(
297       mozc::commands::Command *command,
298       mozc::transliteration::TransliterationType type);
299 
300   // Select a candidate located by input.command.id.  This command
301   // would not be used from SendKey but used from SendCommand because
302   // it requires the argument id.
303   bool SelectCandidate(mozc::commands::Command *command);
304 
305   // Calls SessionConverter::ConmmitFirstSegment() and deletes characters
306   // from the composer.
307   void CommitFirstSegmentInternal(const commands::Context &context);
308 
309   // Calls SessionConverter::ConmmitHeadToFocusedSegments()
310   // and deletes characters from the composer.
311   void CommitHeadToFocusedSegmentsInternal(const commands::Context &context);
312 
313   // Commits without SessionConverter.
314   void CommitCompositionDirectly(commands::Command *command);
315   void CommitSourceTextDirectly(commands::Command *command);
316   void CommitRawTextDirectly(commands::Command *command);
317   void CommitStringDirectly(const string &key, const string &preedit,
318                             commands::Command *command);
319   bool CommitInternal(commands::Command *command,
320                       bool trigger_zero_query_suggest);
321 
322   // Calls SessionConverter::Suggest if the condition is applicable to
323   // call it.  True is returned when SessionConverter::Suggest is
324   // called and results exist.  False is returned when
325   // SessionConverter::Suggest is not called or no results exist.
326   bool Suggest(const mozc::commands::Input &input);
327 
328   // Commands like EditCancel should restore the original string used for
329   // the reverse conversion without any modification.
330   // Returns true if the |source_text| is committed to cancel reconversion.
331   // Returns false if this function has nothing to do.
332   bool TryCancelConvertReverse(mozc::commands::Command *command);
333 
334   // Set the focus to the candidate located by input.command.id.  This
335   // command would not be used from SendKey but used from SendCommand
336   // because it requires the argument id.  The difference from
337   // SelectCandidate is that HighlightCandidate does not close the
338   // candidate window while SelectCandidate closes the candidate
339   // window.
340   bool HighlightCandidate(mozc::commands::Command *command);
341 
342   // The internal implementation of both SelectCandidate and HighlightCandidate.
343   bool SelectCandidateInternal(mozc::commands::Command *command);
344 
345   // If the command is a shortcut to select a candidate from a list,
346   // Process it and return true, otherwise return false.
347   bool MaybeSelectCandidate(mozc::commands::Command *command);
348 
349   // Fill command's output according to the current state.
350   void OutputFromState(mozc::commands::Command *command);
351   void Output(mozc::commands::Command *command);
352   void OutputMode(mozc::commands::Command *command) const;
353   void OutputComposition(mozc::commands::Command *command) const;
354   void OutputKey(mozc::commands::Command *command) const;
355 
356   bool SendKeyDirectInputState(mozc::commands::Command *command);
357   bool SendKeyPrecompositionState(mozc::commands::Command *command);
358   bool SendKeyCompositionState(mozc::commands::Command *command);
359   bool SendKeyConversionState(mozc::commands::Command *command);
360 
361   // update last_command_time;
362   void UpdateTime();
363 
364   // update preferences only affecting this session.
365   void UpdatePreferences(mozc::commands::Command *command);
366 
367   // Modify input of SendKey, TestSendKey, and SendCommand.
368   void TransformInput(mozc::commands::Input *input);
369 
370   // ensure session status is not DIRECT.
371   // if session status is DIRECT, set the status to PRECOMPOSITION.
372   void EnsureIMEIsOn();
373 
374   // return true if |key_event| is a triggering key_event of
375   // AutoIMEConversion.
376   bool CanStartAutoConversion(const mozc::commands::KeyEvent &key_event) const;
377 
378   // Handles KeyEvent::activated to support indirect IME on/off.
379   bool HandleIndirectImeOnOff(mozc::commands::Command *command);
380 
381   // Commits the raw text of the composition.
382   bool CommitRawText(commands::Command *command);
383 
384   DISALLOW_COPY_AND_ASSIGN(Session);
385 };
386 
387 }  // namespace session
388 }  // namespace mozc
389 
390 #endif  // MOZC_SESSION_SESSION_H_
391