blob: 933511e57d2adc5b114e1b3c01a05a2f5da45c96 [file] [log] [blame]
// 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.
#import "content/browser/renderer_host/text_input_client_mac.h"
#include "base/memory/singleton.h"
#include "base/metrics/histogram.h"
#include "base/time.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/text_input_client_messages.h"
using content::RenderWidgetHost;
using content::RenderWidgetHostImpl;
// The amount of time in milliseconds that the browser process will wait for a
// response from the renderer.
// TODO(rsesek): Using the histogram data, find the best upper-bound for this
// value.
const float kWaitTimeout = 1500;
TextInputClientMac::TextInputClientMac()
: character_index_(NSNotFound),
lock_(),
condition_(&lock_) {
}
TextInputClientMac::~TextInputClientMac() {
}
// static
TextInputClientMac* TextInputClientMac::GetInstance() {
return Singleton<TextInputClientMac>::get();
}
NSUInteger TextInputClientMac::GetCharacterIndexAtPoint(RenderWidgetHost* rwh,
gfx::Point point) {
base::TimeTicks start = base::TimeTicks::Now();
BeforeRequest();
RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
rwhi->Send(new TextInputClientMsg_CharacterIndexForPoint(rwhi->GetRoutingID(),
point));
condition_.TimedWait(base::TimeDelta::FromMilliseconds(kWaitTimeout));
AfterRequest();
base::TimeDelta delta(base::TimeTicks::Now() - start);
UMA_HISTOGRAM_TIMES("TextInputClient.CharacterIndex",
delta * base::Time::kMicrosecondsPerMillisecond);
return character_index_;
}
NSRect TextInputClientMac::GetFirstRectForRange(RenderWidgetHost* rwh,
NSRange range) {
base::TimeTicks start = base::TimeTicks::Now();
BeforeRequest();
RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
rwhi->Send(
new TextInputClientMsg_FirstRectForCharacterRange(rwhi->GetRoutingID(),
ui::Range(range)));
condition_.TimedWait(base::TimeDelta::FromMilliseconds(kWaitTimeout));
AfterRequest();
base::TimeDelta delta(base::TimeTicks::Now() - start);
UMA_HISTOGRAM_TIMES("TextInputClient.FirstRect",
delta * base::Time::kMicrosecondsPerMillisecond);
return first_rect_;
}
NSAttributedString* TextInputClientMac::GetAttributedSubstringFromRange(
RenderWidgetHost* rwh,
NSRange range) {
base::TimeTicks start = base::TimeTicks::Now();
BeforeRequest();
RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
rwhi->Send(new TextInputClientMsg_StringForRange(rwhi->GetRoutingID(),
ui::Range(range)));
condition_.TimedWait(base::TimeDelta::FromMilliseconds(kWaitTimeout));
AfterRequest();
base::TimeDelta delta(base::TimeTicks::Now() - start);
UMA_HISTOGRAM_TIMES("TextInputClient.Substring",
delta * base::Time::kMicrosecondsPerMillisecond);
// Lookup.framework calls this method repeatedly and expects that repeated
// calls don't deallocate previous results immediately. Returning an
// autoreleased string is better convention anyway.
return [[substring_.get() retain] autorelease];
}
void TextInputClientMac::SetCharacterIndexAndSignal(NSUInteger index) {
lock_.Acquire();
character_index_ = index;
lock_.Release();
condition_.Signal();
}
void TextInputClientMac::SetFirstRectAndSignal(NSRect first_rect) {
lock_.Acquire();
first_rect_ = first_rect;
lock_.Release();
condition_.Signal();
}
void TextInputClientMac::SetSubstringAndSignal(NSAttributedString* string) {
lock_.Acquire();
substring_.reset([string copy]);
lock_.Release();
condition_.Signal();
}
void TextInputClientMac::BeforeRequest() {
base::TimeTicks start = base::TimeTicks::Now();
lock_.Acquire();
base::TimeDelta delta(base::TimeTicks::Now() - start);
UMA_HISTOGRAM_TIMES("TextInputClient.LockWait",
delta * base::Time::kMicrosecondsPerMillisecond);
character_index_ = NSNotFound;
first_rect_ = NSZeroRect;
substring_.reset();
}
void TextInputClientMac::AfterRequest() {
lock_.Release();
}