1// Copyright (c) 2012 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 CHROME_BROWSER_TAB_CONTENTS_SPELLING_MENU_OBSERVER_H_
6#define CHROME_BROWSER_TAB_CONTENTS_SPELLING_MENU_OBSERVER_H_
7
8#include <vector>
9
10#include "base/compiler_specific.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/prefs/pref_member.h"
13#include "base/strings/string16.h"
14#include "base/timer/timer.h"
15#include "chrome/browser/spellchecker/spelling_service_client.h"
16#include "chrome/browser/tab_contents/render_view_context_menu_observer.h"
17
18class RenderViewContextMenuProxy;
19struct SpellCheckResult;
20
21// An observer that listens to events from the RenderViewContextMenu class and
22// shows suggestions from the Spelling ("do you mean") service to a context menu
23// while we show it. This class implements two interfaces:
24// * RenderViewContextMenuObserver
25//   This interface is used for adding a menu item and update it while showing.
26// * net::URLFetcherDelegate
27//   This interface is used for sending a JSON_RPC request to the Spelling
28//   service and retrieving its response.
29// These interfaces allow this class to make a JSON-RPC call to the Spelling
30// service in the background and update the context menu while showing. The
31// following snippet describes how to add this class to the observer list of the
32// RenderViewContextMenu class.
33//
34//   void RenderViewContextMenu::InitMenu() {
35//     spelling_menu_observer_.reset(new SpellingMenuObserver(this));
36//     if (spelling_menu_observer_.get())
37//       observers_.AddObserver(spelling_menu_observer.get());
38//   }
39//
40class SpellingMenuObserver : public RenderViewContextMenuObserver {
41 public:
42  explicit SpellingMenuObserver(RenderViewContextMenuProxy* proxy);
43  virtual ~SpellingMenuObserver();
44
45  // RenderViewContextMenuObserver implementation.
46  virtual void InitMenu(const content::ContextMenuParams& params) OVERRIDE;
47  virtual bool IsCommandIdSupported(int command_id) OVERRIDE;
48  virtual bool IsCommandIdChecked(int command_id) OVERRIDE;
49  virtual bool IsCommandIdEnabled(int command_id) OVERRIDE;
50  virtual void ExecuteCommand(int command_id) OVERRIDE;
51  virtual void OnMenuCancel() OVERRIDE;
52
53  // A callback function called when the Spelling service finishes checking a
54  // misspelled word.
55  void OnTextCheckComplete(
56      SpellingServiceClient::ServiceType type,
57      bool success,
58      const string16& text,
59      const std::vector<SpellCheckResult>& results);
60
61 private:
62  // The callback function for base::RepeatingTimer<SpellingMenuClient>. This
63  // function updates the "loading..." animation in the context-menu item.
64  void OnAnimationTimerExpired();
65
66  // The interface to add a context-menu item and update it. This class uses
67  // this interface to avoid accesing context-menu items directly.
68  RenderViewContextMenuProxy* proxy_;
69
70  // Suggested words from the local spellchecker. If the spelling service
71  // returns a word in this list, we hide the context-menu item to prevent
72  // showing the same word twice.
73  std::vector<string16> suggestions_;
74
75  // The string used for animation until we receive a response from the Spelling
76  // service. The current animation just adds periods at the end of this string:
77  //   'Loading' -> 'Loading.' -> 'Loading..' -> 'Loading...' (-> 'Loading')
78  string16 loading_message_;
79  size_t loading_frame_;
80
81  // A flag represending whether a JSON-RPC call to the Spelling service
82  // finished successfully and its response had a suggestion not included in the
83  // ones provided by the local spellchecker. When this flag is true, we enable
84  // the context-menu item so users can choose it.
85  bool succeeded_;
86
87  // The misspelled word. When we choose the "Add to dictionary" item, we add
88  // this word to the custom-word dictionary.
89  string16 misspelled_word_;
90
91  // The hash identifier for the misspelled word. Used for collecting user
92  // feedback to spellcheck suggestions.
93  uint32 misspelling_hash_;
94
95  // The string representing the result of this call. This string is a
96  // suggestion when this call finished successfully. Otherwise it is error
97  // text. Until we receive a response from the Spelling service, this string
98  // stores the input string. (Since the Spelling service sends only misspelled
99  // words, we replace these misspelled words in the input text with the
100  // suggested words to create suggestion text.
101  string16 result_;
102
103  // The URLFetcher object used for sending a JSON-RPC request.
104  scoped_ptr<SpellingServiceClient> client_;
105
106  // A timer used for loading animation.
107  base::RepeatingTimer<SpellingMenuObserver> animation_timer_;
108
109  // Flag indicating whether online spelling correction service is enabled. When
110  // this variable is true and we right-click a misspelled word, we send a
111  // JSON-RPC request to the service and retrieve suggestions.
112  BooleanPrefMember integrate_spelling_service_;
113
114  // Flag indicating whether automatic spelling correction is enabled.
115  BooleanPrefMember autocorrect_spelling_;
116
117  DISALLOW_COPY_AND_ASSIGN(SpellingMenuObserver);
118};
119
120#endif  // CHROME_BROWSER_TAB_CONTENTS_SPELLING_MENU_OBSERVER_H_
121