- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / text_input_client_mac.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 "content/browser/renderer_host/text_input_client_mac.h"
6
7 #include "base/memory/singleton.h"
8 #include "base/metrics/histogram.h"
9 #include "base/threading/thread_restrictions.h"
10 #include "base/time/time.h"
11 #include "content/browser/renderer_host/render_widget_host_impl.h"
12 #include "content/common/text_input_client_messages.h"
13
14 namespace content {
15
16 // The amount of time in milliseconds that the browser process will wait for a
17 // response from the renderer.
18 // TODO(rsesek): Using the histogram data, find the best upper-bound for this
19 // value.
20 const float kWaitTimeout = 1500;
21
22 TextInputClientMac::TextInputClientMac()
23     : character_index_(NSNotFound),
24       lock_(),
25       condition_(&lock_) {
26 }
27
28 TextInputClientMac::~TextInputClientMac() {
29 }
30
31 // static
32 TextInputClientMac* TextInputClientMac::GetInstance() {
33   return Singleton<TextInputClientMac>::get();
34 }
35
36 NSUInteger TextInputClientMac::GetCharacterIndexAtPoint(RenderWidgetHost* rwh,
37     gfx::Point point) {
38   base::TimeTicks start = base::TimeTicks::Now();
39
40   BeforeRequest();
41   RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
42   rwhi->Send(new TextInputClientMsg_CharacterIndexForPoint(rwhi->GetRoutingID(),
43                                                           point));
44   // http://crbug.com/121917
45   base::ThreadRestrictions::ScopedAllowWait allow_wait;
46   condition_.TimedWait(base::TimeDelta::FromMilliseconds(kWaitTimeout));
47   AfterRequest();
48
49   base::TimeDelta delta(base::TimeTicks::Now() - start);
50   UMA_HISTOGRAM_LONG_TIMES("TextInputClient.CharacterIndex",
51                            delta * base::Time::kMicrosecondsPerMillisecond);
52
53   return character_index_;
54 }
55
56 NSRect TextInputClientMac::GetFirstRectForRange(RenderWidgetHost* rwh,
57     NSRange range) {
58   base::TimeTicks start = base::TimeTicks::Now();
59
60   BeforeRequest();
61   RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
62   rwhi->Send(
63       new TextInputClientMsg_FirstRectForCharacterRange(rwhi->GetRoutingID(),
64                                                         gfx::Range(range)));
65   // http://crbug.com/121917
66   base::ThreadRestrictions::ScopedAllowWait allow_wait;
67   condition_.TimedWait(base::TimeDelta::FromMilliseconds(kWaitTimeout));
68   AfterRequest();
69
70   base::TimeDelta delta(base::TimeTicks::Now() - start);
71   UMA_HISTOGRAM_LONG_TIMES("TextInputClient.FirstRect",
72                            delta * base::Time::kMicrosecondsPerMillisecond);
73
74   return first_rect_;
75 }
76
77 NSAttributedString* TextInputClientMac::GetAttributedSubstringFromRange(
78     RenderWidgetHost* rwh,
79     NSRange range) {
80   base::TimeTicks start = base::TimeTicks::Now();
81
82   BeforeRequest();
83   RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
84   rwhi->Send(new TextInputClientMsg_StringForRange(rwhi->GetRoutingID(),
85                                                    gfx::Range(range)));
86   // http://crbug.com/121917
87   base::ThreadRestrictions::ScopedAllowWait allow_wait;
88   condition_.TimedWait(base::TimeDelta::FromMilliseconds(kWaitTimeout));
89   AfterRequest();
90
91   base::TimeDelta delta(base::TimeTicks::Now() - start);
92   UMA_HISTOGRAM_LONG_TIMES("TextInputClient.Substring",
93                            delta * base::Time::kMicrosecondsPerMillisecond);
94
95   // Lookup.framework calls this method repeatedly and expects that repeated
96   // calls don't deallocate previous results immediately. Returning an
97   // autoreleased string is better convention anyway.
98   return [[substring_.get() retain] autorelease];
99 }
100
101 void TextInputClientMac::SetCharacterIndexAndSignal(NSUInteger index) {
102   lock_.Acquire();
103   character_index_ = index;
104   lock_.Release();
105   condition_.Signal();
106 }
107
108 void TextInputClientMac::SetFirstRectAndSignal(NSRect first_rect) {
109   lock_.Acquire();
110   first_rect_ = first_rect;
111   lock_.Release();
112   condition_.Signal();
113 }
114
115 void TextInputClientMac::SetSubstringAndSignal(NSAttributedString* string) {
116   lock_.Acquire();
117   substring_.reset([string copy]);
118   lock_.Release();
119   condition_.Signal();
120 }
121
122 void TextInputClientMac::BeforeRequest() {
123   base::TimeTicks start = base::TimeTicks::Now();
124
125   lock_.Acquire();
126
127   base::TimeDelta delta(base::TimeTicks::Now() - start);
128   UMA_HISTOGRAM_LONG_TIMES("TextInputClient.LockWait",
129                            delta * base::Time::kMicrosecondsPerMillisecond);
130
131   character_index_ = NSNotFound;
132   first_rect_ = NSZeroRect;
133   substring_.reset();
134 }
135
136 void TextInputClientMac::AfterRequest() {
137   lock_.Release();
138 }
139
140 }  // namespace content