speech_input_bubble_controller.cc revision 731df977c0511bca2206b5f333555b1205ff1f43
1// Copyright (c) 2010 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#include "chrome/browser/speech/speech_input_bubble_controller.h"
6
7#include "chrome/browser/browser_thread.h"
8#include "chrome/browser/tab_contents/tab_contents.h"
9#include "chrome/browser/tab_contents/tab_util.h"
10#include "gfx/rect.h"
11
12namespace speech_input {
13
14SpeechInputBubbleController::SpeechInputBubbleController(Delegate* delegate)
15    : delegate_(delegate),
16      current_bubble_caller_id_(0) {
17}
18
19SpeechInputBubbleController::~SpeechInputBubbleController() {
20  DCHECK(bubbles_.size() == 0);
21}
22
23void SpeechInputBubbleController::CreateBubble(int caller_id,
24                                               int render_process_id,
25                                               int render_view_id,
26                                               const gfx::Rect& element_rect) {
27  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
28    BrowserThread::PostTask(
29        BrowserThread::UI, FROM_HERE,
30        NewRunnableMethod(this, &SpeechInputBubbleController::CreateBubble,
31                          caller_id, render_process_id, render_view_id,
32                          element_rect));
33    return;
34  }
35  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
36  TabContents* tab_contents = tab_util::GetTabContentsByID(render_process_id,
37                                                           render_view_id);
38
39  DCHECK_EQ(0u, bubbles_.count(caller_id));
40  SpeechInputBubble* bubble = SpeechInputBubble::Create(tab_contents, this,
41                                                        element_rect);
42  if (!bubble)  // could be null if tab or display rect were invalid.
43    return;
44
45  bubbles_[caller_id] = bubble;
46}
47
48void SpeechInputBubbleController::CloseBubble(int caller_id) {
49  ProcessRequestInUiThread(caller_id, REQUEST_CLOSE, string16(), 0);
50}
51
52void SpeechInputBubbleController::SetBubbleRecordingMode(int caller_id) {
53  ProcessRequestInUiThread(caller_id, REQUEST_SET_RECORDING_MODE,
54                           string16(), 0);
55}
56
57void SpeechInputBubbleController::SetBubbleRecognizingMode(int caller_id) {
58  ProcessRequestInUiThread(caller_id, REQUEST_SET_RECOGNIZING_MODE,
59                           string16(), 0);
60}
61
62void SpeechInputBubbleController::SetBubbleInputVolume(int caller_id,
63                                                       float volume) {
64  ProcessRequestInUiThread(caller_id, REQUEST_SET_INPUT_VOLUME, string16(),
65                           volume);
66}
67
68void SpeechInputBubbleController::SetBubbleMessage(int caller_id,
69                                                   const string16& text) {
70  ProcessRequestInUiThread(caller_id, REQUEST_SET_MESSAGE, text, 0);
71}
72
73void SpeechInputBubbleController::ProcessRequestInUiThread(
74    int caller_id, RequestType type, const string16& text, float volume) {
75  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
76    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod(
77        this, &SpeechInputBubbleController::ProcessRequestInUiThread,
78        caller_id, type, text, volume));
79    return;
80  }
81  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
82  // The bubble may have been closed before we got a chance to process this
83  // request. So check before proceeding.
84  if (!bubbles_.count(caller_id))
85    return;
86
87  bool change_active_bubble = (type == REQUEST_SET_RECORDING_MODE ||
88                               type == REQUEST_SET_MESSAGE);
89  if (change_active_bubble) {
90    if (current_bubble_caller_id_ && current_bubble_caller_id_ != caller_id)
91      bubbles_[current_bubble_caller_id_]->Hide();
92    current_bubble_caller_id_ = caller_id;
93  }
94
95  SpeechInputBubble* bubble = bubbles_[caller_id];
96  switch (type) {
97    case REQUEST_SET_RECORDING_MODE:
98      bubble->SetRecordingMode();
99      break;
100    case REQUEST_SET_RECOGNIZING_MODE:
101      bubble->SetRecognizingMode();
102      break;
103    case REQUEST_SET_MESSAGE:
104      bubble->SetMessage(text);
105      break;
106    case REQUEST_SET_INPUT_VOLUME:
107      bubble->SetInputVolume(volume);
108      break;
109    case REQUEST_CLOSE:
110      if (current_bubble_caller_id_ == caller_id)
111        current_bubble_caller_id_ = 0;
112      delete bubble;
113      bubbles_.erase(caller_id);
114      break;
115    default:
116      NOTREACHED();
117      break;
118  }
119
120  if (change_active_bubble)
121    bubble->Show();
122}
123
124void SpeechInputBubbleController::InfoBubbleButtonClicked(
125    SpeechInputBubble::Button button) {
126  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
127  DCHECK(current_bubble_caller_id_);
128
129  BrowserThread::PostTask(
130      BrowserThread::IO, FROM_HERE,
131      NewRunnableMethod(
132          this,
133          &SpeechInputBubbleController::InvokeDelegateButtonClicked,
134          current_bubble_caller_id_, button));
135}
136
137void SpeechInputBubbleController::InfoBubbleFocusChanged() {
138  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
139  DCHECK(current_bubble_caller_id_);
140
141  int old_bubble_caller_id = current_bubble_caller_id_;
142  current_bubble_caller_id_ = 0;
143  bubbles_[old_bubble_caller_id]->Hide();
144
145  BrowserThread::PostTask(
146      BrowserThread::IO, FROM_HERE,
147      NewRunnableMethod(
148          this,
149          &SpeechInputBubbleController::InvokeDelegateFocusChanged,
150          old_bubble_caller_id));
151}
152
153void SpeechInputBubbleController::InvokeDelegateButtonClicked(
154    int caller_id, SpeechInputBubble::Button button) {
155  delegate_->InfoBubbleButtonClicked(caller_id, button);
156}
157
158void SpeechInputBubbleController::InvokeDelegateFocusChanged(int caller_id) {
159  delegate_->InfoBubbleFocusChanged(caller_id);
160}
161
162}  // namespace speech_input
163