summaryrefslogtreecommitdiff
path: root/chromium/content/browser/renderer_host/text_input_client_mac.h
blob: 8165445841da50ea428ebda30e4cf72be1fa02ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_BROWSER_RENDERER_HOST_TEXT_INPUT_CLIENT_MAC_H_
#define CONTENT_BROWSER_RENDERER_HOST_TEXT_INPUT_CLIENT_MAC_H_

#import <Cocoa/Cocoa.h>

#include "base/mac/scoped_block.h"
#include "base/mac/scoped_nsobject.h"
#include "base/macros.h"
#include "base/synchronization/condition_variable.h"
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
#include "content/common/mac/attributed_string_coder.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"

namespace base {
template <typename T>
struct DefaultSingletonTraits;
}  // namespace base

namespace gfx {
class Range;
}

namespace content {
class RenderWidgetHost;

// This class helps with the Mac OS X dictionary popup. For the design overview,
// look at this document:
//   http://dev.chromium.org/developers/design-documents/system-dictionary-pop-up-architecture
//
// This service is used to marshall information for these three methods that are
// implemented in RenderWidgetHostViewMac:
//   -[NSTextInput characterIndexForPoint:]
//   -[NSTextInput attributedSubstringFromRange:]
//   -[NSTextInput firstRectForCharacterRange:]
//
// Because these methods are part of a synchronous system API, implementing them
// requires getting information from the renderer synchronously. Rather than
// using an actual sync IPC message, a normal async ViewMsg is used with a lock
// and condition (managed by this service).
//
// Mac OS 10.8 introduced -[NSResponder quickLookWithEvent:].
// We can use it to implement asynchronous dictionary lookup when the user
// taps a word using three fingers.
// But currently the "Look Up in Dictionary" context menu item still goes
// through the above synchronous IPC.
class CONTENT_EXPORT TextInputClientMac {
 public:
  // Returns the singleton instance.
  static TextInputClientMac* GetInstance();

  // Each of the three methods mentioned above has an associated pair of methods
  // to get data from the renderer. The Get*() methods block the calling thread
  // (always the UI thread) with a short timeout after the async message has
  // been sent to the renderer to lookup the information needed to respond to
  // the system. The Set*AndSignal() methods store the looked up information in
  // this service and signal the condition to allow the Get*() methods to
  // unlock and return that stored value.
  //
  // Returns UINT32_MAX if the request times out or is not completed.
  uint32_t GetCharacterIndexAtPoint(RenderWidgetHost* rwh,
                                    const gfx::Point& point);
  // Returns NSZeroRect if the request times out or is not completed. The result
  // is in WebKit coordinates.
  gfx::Rect GetFirstRectForRange(RenderWidgetHost* rwh,
                                 const gfx::Range& range);

  // When the renderer sends the ViewHostMsg reply, the RenderMessageFilter will
  // call the corresponding method on the IO thread to unlock the condition and
  // allow the Get*() methods to continue/return.
  void SetCharacterIndexAndSignal(uint32_t index);
  void SetFirstRectAndSignal(const gfx::Rect& first_rect);

  typedef base::OnceCallback<
      void(const mac::AttributedStringCoder::EncodedString&, gfx::Point)>
      GetStringCallback;

  // This async method is invoked from RenderWidgetHostViewCocoa's
  // -quickLookWithEvent:, when the user taps a word using 3 fingers.
  // The reply callback will be invoked from the IO thread; the caller is
  // responsible for bouncing to the main thread if necessary.
  // The callback parameters provide the attributed word under the point and
  // the lower left baseline point of the text.
  void GetStringAtPoint(RenderWidgetHost* rwh,
                        const gfx::Point& point,
                        GetStringCallback callback);

  // This is called on the IO thread when we get the renderer's reply for
  // GetStringAtPoint.
  void GetStringAtPointReply(
      const mac::AttributedStringCoder::EncodedString& string,
      const gfx::Point& point);

  // This async method is invoked when browser tries to retreive the text for
  // certain range and doesn't want to wait for the reply from blink.
  // The reply callback will be invoked from the IO thread; the caller is
  // responsible for bouncing to the main thread if necessary.
  // The callback parameters provide the attributed word under the point and
  // the lower left baseline point of the text.
  void GetStringFromRange(RenderWidgetHost* rwh,
                          const gfx::Range& range,
                          GetStringCallback callback);

  // This is called on the IO thread when we get the renderer's reply for
  // GetStringFromRange.
  void GetStringFromRangeReply(
      const mac::AttributedStringCoder::EncodedString& string,
      const gfx::Point& point);

 private:
  friend struct base::DefaultSingletonTraits<TextInputClientMac>;
  TextInputClientMac();
  ~TextInputClientMac();

  // The critical sections that the Condition guards are in Get*() methods.
  // These methods lock the internal condition for use before the asynchronous
  // message is sent to the renderer to lookup the required information. These
  // are only used on the UI thread.
  void BeforeRequest();
  // Called at the end of a critical section. This will release the lock and
  // condition.
  void AfterRequest();

  uint32_t character_index_;
  gfx::Rect first_rect_;

  base::Lock lock_;
  base::ConditionVariable condition_;

  // The callback when received IPC TextInputClientReplyMsg_GotStringAtPoint.
  GetStringCallback replyForPointHandler_;

  // The callback when received IPC TextInputClientReplyMsg_GotStringForRange.
  GetStringCallback replyForRangeHandler_;

  DISALLOW_COPY_AND_ASSIGN(TextInputClientMac);
};

}  // namespace content

#endif  // CONTENT_BROWSER_RENDERER_HOST_TEXT_INPUT_CLIENT_MAC_H_