summaryrefslogtreecommitdiffstats
path: root/chrome/browser/renderer_host/text_input_client_mac.mm
blob: a8f7c7548110794213ea9c78f9e6c3b5d3e085b7 (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
// Copyright (c) 2011 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 "chrome/browser/renderer_host/text_input_client_mac.h"

#include "base/memory/singleton.h"
#include "base/metrics/histogram.h"
#include "base/time.h"
#include "chrome/common/text_input_client_messages.h"
#include "content/browser/renderer_host/render_widget_host.h"

// 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();
  rwh->Send(new TextInputClientMsg_CharacterIndexForPoint(rwh->routing_id(),
      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();
  rwh->Send(new TextInputClientMsg_FirstRectForCharacterRange(rwh->routing_id(),
      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();
  rwh->Send(new TextInputClientMsg_StringForRange(rwh->routing_id(),
      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();
}