1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#ifndef CHROME_BROWSER_RENDERER_CONTEXT_MENU_SPELLING_MENU_OBSERVER_H_
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#define CHROME_BROWSER_RENDERER_CONTEXT_MENU_SPELLING_MENU_OBSERVER_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_member.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h"
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/renderer_context_menu/render_view_context_menu_observer.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/spellchecker/spelling_service_client.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RenderViewContextMenuProxy;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct SpellCheckResult;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An observer that listens to events from the RenderViewContextMenu class and
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// shows suggestions from the Spelling ("do you mean") service to a context menu
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// while we show it. This class implements two interfaces:
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * RenderViewContextMenuObserver
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   This interface is used for adding a menu item and update it while showing.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * net::URLFetcherDelegate
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   This interface is used for sending a JSON_RPC request to the Spelling
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   service and retrieving its response.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These interfaces allow this class to make a JSON-RPC call to the Spelling
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// service in the background and update the context menu while showing. The
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// following snippet describes how to add this class to the observer list of the
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RenderViewContextMenu class.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   void RenderViewContextMenu::InitMenu() {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     spelling_menu_observer_.reset(new SpellingMenuObserver(this));
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     if (spelling_menu_observer_.get())
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       observers_.AddObserver(spelling_menu_observer.get());
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   }
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SpellingMenuObserver : public RenderViewContextMenuObserver {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit SpellingMenuObserver(RenderViewContextMenuProxy* proxy);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SpellingMenuObserver();
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RenderViewContextMenuObserver implementation.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void InitMenu(const content::ContextMenuParams& params) OVERRIDE;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool IsCommandIdSupported(int command_id) OVERRIDE;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool IsCommandIdChecked(int command_id) OVERRIDE;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool IsCommandIdEnabled(int command_id) OVERRIDE;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ExecuteCommand(int command_id) OVERRIDE;
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void OnMenuCancel() OVERRIDE;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A callback function called when the Spelling service finishes checking a
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // misspelled word.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnTextCheckComplete(
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SpellingServiceClient::ServiceType type,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool success,
58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const base::string16& text,
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::vector<SpellCheckResult>& results);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The callback function for base::RepeatingTimer<SpellingMenuClient>. This
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // function updates the "loading..." animation in the context-menu item.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnAnimationTimerExpired();
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The interface to add a context-menu item and update it. This class uses
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this interface to avoid accesing context-menu items directly.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RenderViewContextMenuProxy* proxy_;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Suggested words from the local spellchecker. If the spelling service
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returns a word in this list, we hide the context-menu item to prevent
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // showing the same word twice.
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<base::string16> suggestions_;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The string used for animation until we receive a response from the Spelling
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // service. The current animation just adds periods at the end of this string:
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   'Loading' -> 'Loading.' -> 'Loading..' -> 'Loading...' (-> 'Loading')
78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 loading_message_;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t loading_frame_;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A flag represending whether a JSON-RPC call to the Spelling service
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // finished successfully and its response had a suggestion not included in the
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ones provided by the local spellchecker. When this flag is true, we enable
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the context-menu item so users can choose it.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool succeeded_;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The misspelled word. When we choose the "Add to dictionary" item, we add
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this word to the custom-word dictionary.
89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 misspelled_word_;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The hash identifier for the misspelled word. Used for collecting user
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // feedback to spellcheck suggestions.
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  uint32 misspelling_hash_;
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The string representing the result of this call. This string is a
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // suggestion when this call finished successfully. Otherwise it is error
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // text. Until we receive a response from the Spelling service, this string
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // stores the input string. (Since the Spelling service sends only misspelled
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // words, we replace these misspelled words in the input text with the
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // suggested words to create suggestion text.
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 result_;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The URLFetcher object used for sending a JSON-RPC request.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpellingServiceClient> client_;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A timer used for loading animation.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::RepeatingTimer<SpellingMenuObserver> animation_timer_;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flag indicating whether online spelling correction service is enabled. When
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this variable is true and we right-click a misspelled word, we send a
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // JSON-RPC request to the service and retrieve suggestions.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BooleanPrefMember integrate_spelling_service_;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Flag indicating whether automatic spelling correction is enabled.
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BooleanPrefMember autocorrect_spelling_;
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SpellingMenuObserver);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif  // CHROME_BROWSER_RENDERER_CONTEXT_MENU_SPELLING_MENU_OBSERVER_H_
121