Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / renderer_host / chrome_render_widget_host_view_mac_delegate.mm
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 #import "chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.h"
6
7 #include <cmath>
8
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/sys_string_conversions.h"
11 #include "chrome/browser/devtools/devtools_window.h"
12 #include "chrome/browser/profiles/profile.h"
13 #import "chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.h"
14 #include "chrome/browser/spellchecker/spellcheck_platform_mac.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/browser_commands.h"
17 #include "chrome/browser/ui/browser_finder.h"
18 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
19 #include "chrome/common/pref_names.h"
20 #include "chrome/common/spellcheck_messages.h"
21 #include "chrome/common/url_constants.h"
22 #include "content/public/browser/render_process_host.h"
23 #include "content/public/browser/render_view_host.h"
24 #include "content/public/browser/render_widget_host.h"
25 #include "content/public/browser/render_widget_host_view.h"
26 #include "content/public/browser/web_contents.h"
27 #include "content/public/browser/web_contents_observer.h"
28
29 using content::RenderViewHost;
30
31 @interface ChromeRenderWidgetHostViewMacDelegate () <HistorySwiperDelegate>
32 - (void)spellCheckEnabled:(BOOL)enabled checked:(BOOL)checked;
33 @end
34
35 namespace ChromeRenderWidgetHostViewMacDelegateInternal {
36
37 // Filters the message sent by the renderer to know if spellchecking is enabled
38 // or not for the currently focused element.
39 class SpellCheckObserver : public content::WebContentsObserver {
40  public:
41   SpellCheckObserver(
42       RenderViewHost* host,
43       ChromeRenderWidgetHostViewMacDelegate* view_delegate)
44       : content::WebContentsObserver(
45             content::WebContents::FromRenderViewHost(host)),
46         view_delegate_(view_delegate) {
47   }
48
49   ~SpellCheckObserver() override {}
50
51  private:
52   bool OnMessageReceived(const IPC::Message& message) override {
53     bool handled = true;
54     IPC_BEGIN_MESSAGE_MAP(SpellCheckObserver, message)
55       IPC_MESSAGE_HANDLER(SpellCheckHostMsg_ToggleSpellCheck,
56                           OnToggleSpellCheck)
57       IPC_MESSAGE_UNHANDLED(handled = false)
58     IPC_END_MESSAGE_MAP()
59     return handled;
60   }
61
62   void OnToggleSpellCheck(bool enabled, bool checked) {
63     [view_delegate_ spellCheckEnabled:enabled checked:checked];
64   }
65
66   ChromeRenderWidgetHostViewMacDelegate* view_delegate_;
67 };
68
69 }  // namespace ChromeRenderWidgetHostViewMacDelegateInternal
70
71 @implementation ChromeRenderWidgetHostViewMacDelegate
72
73 - (id)initWithRenderWidgetHost:(content::RenderWidgetHost*)renderWidgetHost {
74   self = [super init];
75   if (self) {
76     renderWidgetHost_ = renderWidgetHost;
77     if (renderWidgetHost_->IsRenderView()) {
78       spellingObserver_.reset(
79           new ChromeRenderWidgetHostViewMacDelegateInternal::SpellCheckObserver(
80               RenderViewHost::From(renderWidgetHost_), self));
81     }
82
83     historySwiper_.reset([[HistorySwiper alloc] initWithDelegate:self]);
84   }
85   return self;
86 }
87
88 - (void)dealloc {
89   [historySwiper_ setDelegate:nil];
90   [super dealloc];
91 }
92
93 // Handle an event. All incoming key and mouse events flow through this
94 // delegate method if implemented. Return YES if the event is fully handled, or
95 // NO if normal processing should take place.
96 - (BOOL)handleEvent:(NSEvent*)event {
97   return [historySwiper_ handleEvent:event];
98 }
99
100 // NSWindow events.
101
102 - (void)beginGestureWithEvent:(NSEvent*)event {
103   [historySwiper_ beginGestureWithEvent:event];
104 }
105
106 - (void)endGestureWithEvent:(NSEvent*)event {
107   [historySwiper_ endGestureWithEvent:event];
108 }
109
110 // This is a low level API which provides touches associated with an event.
111 // It is used in conjunction with gestures to determine finger placement
112 // on the trackpad.
113 - (void)touchesMovedWithEvent:(NSEvent*)event {
114   [historySwiper_ touchesMovedWithEvent:event];
115 }
116
117 - (void)touchesBeganWithEvent:(NSEvent*)event {
118   [historySwiper_ touchesBeganWithEvent:event];
119 }
120
121 - (void)touchesCancelledWithEvent:(NSEvent*)event {
122   [historySwiper_ touchesCancelledWithEvent:event];
123 }
124
125 - (void)touchesEndedWithEvent:(NSEvent*)event {
126   [historySwiper_ touchesEndedWithEvent:event];
127 }
128
129 - (BOOL)canRubberbandLeft:(NSView*)view {
130   return [historySwiper_ canRubberbandLeft:view];
131 }
132
133 - (BOOL)canRubberbandRight:(NSView*)view {
134   return [historySwiper_ canRubberbandRight:view];
135 }
136
137 // HistorySwiperDelegate methods
138
139 - (BOOL)shouldAllowHistorySwiping {
140   if (!renderWidgetHost_ || !renderWidgetHost_->IsRenderView())
141     return NO;
142   content::WebContents* webContents = content::WebContents::FromRenderViewHost(
143       RenderViewHost::From(renderWidgetHost_));
144   if (webContents && DevToolsWindow::IsDevToolsWindow(webContents)) {
145     return NO;
146   }
147
148   return YES;
149 }
150
151 - (NSView*)viewThatWantsHistoryOverlay {
152   return renderWidgetHost_->GetView()->GetNativeView();
153 }
154
155 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item
156                       isValidItem:(BOOL*)valid {
157   SEL action = [item action];
158
159   // For now, this action is always enabled for render view;
160   // this is sub-optimal.
161   // TODO(suzhe): Plumb the "can*" methods up from WebCore.
162   if (action == @selector(checkSpelling:)) {
163     *valid = renderWidgetHost_->IsRenderView();
164     return YES;
165   }
166
167   // TODO(groby): Clarify who sends this and if toggleContinuousSpellChecking:
168   // is still necessary.
169   if (action == @selector(toggleContinuousSpellChecking:)) {
170     if ([(id)item respondsToSelector:@selector(setState:)]) {
171       content::RenderProcessHost* host = renderWidgetHost_->GetProcess();
172       Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext());
173       DCHECK(profile);
174       spellcheckChecked_ =
175           profile->GetPrefs()->GetBoolean(prefs::kEnableContinuousSpellcheck);
176       NSCellStateValue checkedState =
177           spellcheckChecked_ ? NSOnState : NSOffState;
178       [(id)item setState:checkedState];
179     }
180     *valid = spellcheckEnabled_;
181     return YES;
182   }
183
184   return NO;
185 }
186
187 - (void)rendererHandledWheelEvent:(const blink::WebMouseWheelEvent&)event
188                          consumed:(BOOL)consumed {
189   [historySwiper_ rendererHandledWheelEvent:event consumed:consumed];
190 }
191
192 // Spellchecking methods
193 // The next five methods are implemented here since this class is the first
194 // responder for anything in the browser.
195
196 // This message is sent whenever the user specifies that a word should be
197 // changed from the spellChecker.
198 - (void)changeSpelling:(id)sender {
199   // Grab the currently selected word from the spell panel, as this is the word
200   // that we want to replace the selected word in the text with.
201   NSString* newWord = [[sender selectedCell] stringValue];
202   if (newWord != nil) {
203     content::WebContents* webContents =
204         content::WebContents::FromRenderViewHost(
205             RenderViewHost::From(renderWidgetHost_));
206     webContents->Replace(base::SysNSStringToUTF16(newWord));
207   }
208 }
209
210 // This message is sent by NSSpellChecker whenever the next word should be
211 // advanced to, either after a correction or clicking the "Find Next" button.
212 // This isn't documented anywhere useful, like in NSSpellProtocol.h with the
213 // other spelling panel methods. This is probably because Apple assumes that the
214 // the spelling panel will be used with an NSText, which will automatically
215 // catch this and advance to the next word for you. Thanks Apple.
216 // This is also called from the Edit -> Spelling -> Check Spelling menu item.
217 - (void)checkSpelling:(id)sender {
218   renderWidgetHost_->Send(new SpellCheckMsg_AdvanceToNextMisspelling(
219       renderWidgetHost_->GetRoutingID()));
220 }
221
222 // This message is sent by the spelling panel whenever a word is ignored.
223 - (void)ignoreSpelling:(id)sender {
224   // Ideally, we would ask the current RenderView for its tag, but that would
225   // mean making a blocking IPC call from the browser. Instead,
226   // spellcheck_mac::CheckSpelling remembers the last tag and
227   // spellcheck_mac::IgnoreWord assumes that is the correct tag.
228   NSString* wordToIgnore = [sender stringValue];
229   if (wordToIgnore != nil)
230     spellcheck_mac::IgnoreWord(base::SysNSStringToUTF16(wordToIgnore));
231 }
232
233 - (void)showGuessPanel:(id)sender {
234   renderWidgetHost_->Send(new SpellCheckMsg_ToggleSpellPanel(
235       renderWidgetHost_->GetRoutingID(),
236       spellcheck_mac::SpellingPanelVisible()));
237 }
238
239 - (void)toggleContinuousSpellChecking:(id)sender {
240   content::RenderProcessHost* host = renderWidgetHost_->GetProcess();
241   Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext());
242   DCHECK(profile);
243   PrefService* pref = profile->GetPrefs();
244   pref->SetBoolean(prefs::kEnableContinuousSpellcheck,
245                    !pref->GetBoolean(prefs::kEnableContinuousSpellcheck));
246 }
247
248 - (void)spellCheckEnabled:(BOOL)enabled checked:(BOOL)checked {
249   spellcheckEnabled_ = enabled;
250   spellcheckChecked_ = checked;
251 }
252
253 // END Spellchecking methods
254
255 @end