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.
5 #import "content/browser/renderer_host/text_input_client_mac.h"
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"
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
20 const float kWaitTimeout = 1500;
22 TextInputClientMac::TextInputClientMac()
23 : character_index_(NSNotFound),
28 TextInputClientMac::~TextInputClientMac() {
32 TextInputClientMac* TextInputClientMac::GetInstance() {
33 return base::Singleton<TextInputClientMac>::get();
36 void TextInputClientMac::GetStringAtPoint(
37 RenderWidgetHost* rwh,
39 void (^replyHandler)(NSAttributedString*, NSPoint)) {
40 DCHECK(replyHandler_.get() == nil);
41 replyHandler_.reset(replyHandler, base::scoped_policy::RETAIN);
42 RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
43 rwhi->Send(new TextInputClientMsg_StringAtPoint(rwhi->GetRoutingID(), point));
46 void TextInputClientMac::GetStringAtPointReply(NSAttributedString* string,
48 if (replyHandler_.get()) {
49 replyHandler_.get()(string, point);
50 replyHandler_.reset();
54 NSUInteger TextInputClientMac::GetCharacterIndexAtPoint(RenderWidgetHost* rwh,
56 base::TimeTicks start = base::TimeTicks::Now();
59 RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
60 rwhi->Send(new TextInputClientMsg_CharacterIndexForPoint(rwhi->GetRoutingID(),
62 // http://crbug.com/121917
63 base::ThreadRestrictions::ScopedAllowWait allow_wait;
64 condition_.TimedWait(base::TimeDelta::FromMilliseconds(kWaitTimeout));
67 base::TimeDelta delta(base::TimeTicks::Now() - start);
68 UMA_HISTOGRAM_LONG_TIMES("TextInputClient.CharacterIndex",
69 delta * base::Time::kMicrosecondsPerMillisecond);
71 return character_index_;
74 NSRect TextInputClientMac::GetFirstRectForRange(RenderWidgetHost* rwh,
76 base::TimeTicks start = base::TimeTicks::Now();
79 RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
81 new TextInputClientMsg_FirstRectForCharacterRange(rwhi->GetRoutingID(),
83 // http://crbug.com/121917
84 base::ThreadRestrictions::ScopedAllowWait allow_wait;
85 condition_.TimedWait(base::TimeDelta::FromMilliseconds(kWaitTimeout));
88 base::TimeDelta delta(base::TimeTicks::Now() - start);
89 UMA_HISTOGRAM_LONG_TIMES("TextInputClient.FirstRect",
90 delta * base::Time::kMicrosecondsPerMillisecond);
95 NSAttributedString* TextInputClientMac::GetAttributedSubstringFromRange(
96 RenderWidgetHost* rwh,
98 base::TimeTicks start = base::TimeTicks::Now();
101 RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
102 rwhi->Send(new TextInputClientMsg_StringForRange(rwhi->GetRoutingID(),
104 // http://crbug.com/121917
105 base::ThreadRestrictions::ScopedAllowWait allow_wait;
106 condition_.TimedWait(base::TimeDelta::FromMilliseconds(kWaitTimeout));
109 base::TimeDelta delta(base::TimeTicks::Now() - start);
110 UMA_HISTOGRAM_LONG_TIMES("TextInputClient.Substring",
111 delta * base::Time::kMicrosecondsPerMillisecond);
113 // Lookup.framework calls this method repeatedly and expects that repeated
114 // calls don't deallocate previous results immediately. Returning an
115 // autoreleased string is better convention anyway.
116 return [[substring_.get() retain] autorelease];
119 void TextInputClientMac::SetCharacterIndexAndSignal(NSUInteger index) {
121 character_index_ = index;
126 void TextInputClientMac::SetFirstRectAndSignal(NSRect first_rect) {
128 first_rect_ = first_rect;
133 void TextInputClientMac::SetSubstringAndSignal(NSAttributedString* string) {
135 substring_.reset([string copy]);
140 void TextInputClientMac::BeforeRequest() {
141 base::TimeTicks start = base::TimeTicks::Now();
145 base::TimeDelta delta(base::TimeTicks::Now() - start);
146 UMA_HISTOGRAM_LONG_TIMES("TextInputClient.LockWait",
147 delta * base::Time::kMicrosecondsPerMillisecond);
149 character_index_ = NSNotFound;
150 first_rect_ = NSZeroRect;
154 void TextInputClientMac::AfterRequest() {
158 } // namespace content