Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1446)

Side by Side Diff: chrome/browser/speech/speech_input_bubble_controller.cc

Issue 6115001: Listen for tab close notifications and cancel active speech sessions. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/speech/speech_input_bubble_controller.h" 5 #include "chrome/browser/speech/speech_input_bubble_controller.h"
6 6
7 #include "chrome/browser/browser_thread.h" 7 #include "chrome/browser/browser_thread.h"
8 #include "chrome/browser/tab_contents/tab_contents.h" 8 #include "chrome/browser/tab_contents/tab_contents.h"
9 #include "chrome/browser/tab_contents/tab_util.h" 9 #include "chrome/browser/tab_contents/tab_util.h"
10 #include "chrome/common/notification_registrar.h"
11 #include "chrome/common/notification_source.h"
12 #include "chrome/common/notification_type.h"
10 #include "gfx/rect.h" 13 #include "gfx/rect.h"
11 14
12 namespace speech_input { 15 namespace speech_input {
13 16
14 SpeechInputBubbleController::SpeechInputBubbleController(Delegate* delegate) 17 SpeechInputBubbleController::SpeechInputBubbleController(Delegate* delegate)
15 : delegate_(delegate), 18 : delegate_(delegate),
16 current_bubble_caller_id_(0) { 19 current_bubble_caller_id_(0),
20 registrar_(new NotificationRegistrar) {
17 } 21 }
18 22
19 SpeechInputBubbleController::~SpeechInputBubbleController() { 23 SpeechInputBubbleController::~SpeechInputBubbleController() {
20 DCHECK(bubbles_.size() == 0); 24 DCHECK(bubbles_.size() == 0);
21 } 25 }
22 26
23 void SpeechInputBubbleController::CreateBubble(int caller_id, 27 void SpeechInputBubbleController::CreateBubble(int caller_id,
24 int render_process_id, 28 int render_process_id,
25 int render_view_id, 29 int render_view_id,
26 const gfx::Rect& element_rect) { 30 const gfx::Rect& element_rect) {
27 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 31 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
28 BrowserThread::PostTask( 32 BrowserThread::PostTask(
29 BrowserThread::UI, FROM_HERE, 33 BrowserThread::UI, FROM_HERE,
30 NewRunnableMethod(this, &SpeechInputBubbleController::CreateBubble, 34 NewRunnableMethod(this, &SpeechInputBubbleController::CreateBubble,
31 caller_id, render_process_id, render_view_id, 35 caller_id, render_process_id, render_view_id,
32 element_rect)); 36 element_rect));
33 return; 37 return;
34 } 38 }
35 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 39 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
36 TabContents* tab_contents = tab_util::GetTabContentsByID(render_process_id, 40 TabContents* tab_contents = tab_util::GetTabContentsByID(render_process_id,
37 render_view_id); 41 render_view_id);
38 42
39 DCHECK_EQ(0u, bubbles_.count(caller_id)); 43 DCHECK_EQ(0u, bubbles_.count(caller_id));
40 SpeechInputBubble* bubble = SpeechInputBubble::Create(tab_contents, this, 44 SpeechInputBubble* bubble = SpeechInputBubble::Create(tab_contents, this,
41 element_rect); 45 element_rect);
42 if (!bubble) // could be null if tab or display rect were invalid. 46 if (!bubble) // could be null if tab or display rect were invalid.
43 return; 47 return;
44 48
45 bubbles_[caller_id] = bubble; 49 bubbles_[caller_id] = bubble;
50
51 // If this is the first bubble in our list for this TabContents, register
hans 2011/01/06 12:30:54 "First in our list", but the call is to IsOnlyBubb
52 // for notifications when the tab closes. This ensures that we can safely
53 // kill the bubble and recording session even if the user clicked on the
54 // speech button and immediately closes the tab, or if the tab crashes in
bulach 2011/01/06 12:32:39 s/in the somewhere/
55 // the somewhere while the bubble & recording are active.
hans 2011/01/06 12:30:54 nit: "crashes in the somewhere" sounds weird
56 if (IsOnlyBubbleForTab(caller_id)) {
bulach 2011/01/06 12:32:39 as we chatted, the "IsOnlyBubbleForTab" is the bes
57 registrar_->Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
58 Source<TabContents>(tab_contents));
59 }
46 } 60 }
47 61
48 void SpeechInputBubbleController::CloseBubble(int caller_id) { 62 void SpeechInputBubbleController::CloseBubble(int caller_id) {
49 ProcessRequestInUiThread(caller_id, REQUEST_CLOSE, string16(), 0); 63 ProcessRequestInUiThread(caller_id, REQUEST_CLOSE, string16(), 0);
50 } 64 }
51 65
52 void SpeechInputBubbleController::SetBubbleRecordingMode(int caller_id) { 66 void SpeechInputBubbleController::SetBubbleRecordingMode(int caller_id) {
53 ProcessRequestInUiThread(caller_id, REQUEST_SET_RECORDING_MODE, 67 ProcessRequestInUiThread(caller_id, REQUEST_SET_RECORDING_MODE,
54 string16(), 0); 68 string16(), 0);
55 } 69 }
56 70
57 void SpeechInputBubbleController::SetBubbleRecognizingMode(int caller_id) { 71 void SpeechInputBubbleController::SetBubbleRecognizingMode(int caller_id) {
58 ProcessRequestInUiThread(caller_id, REQUEST_SET_RECOGNIZING_MODE, 72 ProcessRequestInUiThread(caller_id, REQUEST_SET_RECOGNIZING_MODE,
59 string16(), 0); 73 string16(), 0);
60 } 74 }
61 75
62 void SpeechInputBubbleController::SetBubbleInputVolume(int caller_id, 76 void SpeechInputBubbleController::SetBubbleInputVolume(int caller_id,
63 float volume) { 77 float volume) {
64 ProcessRequestInUiThread(caller_id, REQUEST_SET_INPUT_VOLUME, string16(), 78 ProcessRequestInUiThread(caller_id, REQUEST_SET_INPUT_VOLUME, string16(),
65 volume); 79 volume);
66 } 80 }
67 81
68 void SpeechInputBubbleController::SetBubbleMessage(int caller_id, 82 void SpeechInputBubbleController::SetBubbleMessage(int caller_id,
69 const string16& text) { 83 const string16& text) {
70 ProcessRequestInUiThread(caller_id, REQUEST_SET_MESSAGE, text, 0); 84 ProcessRequestInUiThread(caller_id, REQUEST_SET_MESSAGE, text, 0);
71 } 85 }
72 86
87 bool SpeechInputBubbleController::IsOnlyBubbleForTab(int caller_id) {
88 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
89 TabContents* tab_contents = bubbles_[caller_id]->tab_contents();
90 for (BubbleCallerIdMap::iterator iter = bubbles_.begin();
91 iter != bubbles_.end(); ++iter) {
92 if (iter->second->tab_contents() == tab_contents &&
93 iter->first != caller_id) {
94 // At least one other bubble exists for the same TabContents.
bulach 2011/01/06 12:32:39 yeah, as above, this would be the best place to sa
95 return false;
96 }
97 }
98 return true;
99 }
100
101 void SpeechInputBubbleController::Observe(NotificationType type,
102 const NotificationSource& source,
103 const NotificationDetails& details) {
104 if (type == NotificationType::TAB_CONTENTS_DESTROYED) {
105 // Cancel all bubbles and active recognition sessions for this tab.
106 TabContents* tab_contents = Source<TabContents>(source).ptr();
107 BubbleCallerIdMap::iterator iter = bubbles_.begin();
108 while (iter != bubbles_.end()) {
109 if (iter->second->tab_contents() == tab_contents) {
110 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
111 NewRunnableMethod(
112 this,
113 &SpeechInputBubbleController::InvokeDelegateButtonClicked,
114 iter->first, SpeechInputBubble::BUTTON_CANCEL));
115 CloseBubble(iter->first);
116 // We expect to have a very small number of items in this map so
117 // redo-ing from start is ok.
118 iter = bubbles_.begin();
119 } else {
120 ++iter;
121 }
122 }
123 } else {
124 NOTREACHED() << "Unknown notification";
125 }
126 }
127
73 void SpeechInputBubbleController::ProcessRequestInUiThread( 128 void SpeechInputBubbleController::ProcessRequestInUiThread(
74 int caller_id, RequestType type, const string16& text, float volume) { 129 int caller_id, RequestType type, const string16& text, float volume) {
75 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 130 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
76 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod( 131 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod(
77 this, &SpeechInputBubbleController::ProcessRequestInUiThread, 132 this, &SpeechInputBubbleController::ProcessRequestInUiThread,
78 caller_id, type, text, volume)); 133 caller_id, type, text, volume));
79 return; 134 return;
80 } 135 }
81 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
82 // The bubble may have been closed before we got a chance to process this 137 // The bubble may have been closed before we got a chance to process this
(...skipping 19 matching lines...) Expand all
102 break; 157 break;
103 case REQUEST_SET_MESSAGE: 158 case REQUEST_SET_MESSAGE:
104 bubble->SetMessage(text); 159 bubble->SetMessage(text);
105 break; 160 break;
106 case REQUEST_SET_INPUT_VOLUME: 161 case REQUEST_SET_INPUT_VOLUME:
107 bubble->SetInputVolume(volume); 162 bubble->SetInputVolume(volume);
108 break; 163 break;
109 case REQUEST_CLOSE: 164 case REQUEST_CLOSE:
110 if (current_bubble_caller_id_ == caller_id) 165 if (current_bubble_caller_id_ == caller_id)
111 current_bubble_caller_id_ = 0; 166 current_bubble_caller_id_ = 0;
167 // If this is the last bubble for this TabContents, unregister from
168 // close notifications.
169 if (IsOnlyBubbleForTab(caller_id)) {
170 registrar_->Remove(this, NotificationType::TAB_CONTENTS_DESTROYED,
171 Source<TabContents>(bubble->tab_contents()));
172 }
112 delete bubble; 173 delete bubble;
113 bubbles_.erase(caller_id); 174 bubbles_.erase(caller_id);
114 break; 175 break;
115 default: 176 default:
116 NOTREACHED(); 177 NOTREACHED();
117 break; 178 break;
118 } 179 }
119 180
120 if (change_active_bubble) 181 if (change_active_bubble)
121 bubble->Show(); 182 bubble->Show();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 void SpeechInputBubbleController::InvokeDelegateButtonClicked( 214 void SpeechInputBubbleController::InvokeDelegateButtonClicked(
154 int caller_id, SpeechInputBubble::Button button) { 215 int caller_id, SpeechInputBubble::Button button) {
155 delegate_->InfoBubbleButtonClicked(caller_id, button); 216 delegate_->InfoBubbleButtonClicked(caller_id, button);
156 } 217 }
157 218
158 void SpeechInputBubbleController::InvokeDelegateFocusChanged(int caller_id) { 219 void SpeechInputBubbleController::InvokeDelegateFocusChanged(int caller_id) {
159 delegate_->InfoBubbleFocusChanged(caller_id); 220 delegate_->InfoBubbleFocusChanged(caller_id);
160 } 221 }
161 222
162 } // namespace speech_input 223 } // namespace speech_input
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698