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

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 UpdateTabContentsSubscription(caller_id, BUBBLE_ADDED);
46 } 52 }
47 53
48 void SpeechInputBubbleController::CloseBubble(int caller_id) { 54 void SpeechInputBubbleController::CloseBubble(int caller_id) {
49 ProcessRequestInUiThread(caller_id, REQUEST_CLOSE, string16(), 0); 55 ProcessRequestInUiThread(caller_id, REQUEST_CLOSE, string16(), 0);
50 } 56 }
51 57
52 void SpeechInputBubbleController::SetBubbleRecordingMode(int caller_id) { 58 void SpeechInputBubbleController::SetBubbleRecordingMode(int caller_id) {
53 ProcessRequestInUiThread(caller_id, REQUEST_SET_RECORDING_MODE, 59 ProcessRequestInUiThread(caller_id, REQUEST_SET_RECORDING_MODE,
54 string16(), 0); 60 string16(), 0);
55 } 61 }
56 62
57 void SpeechInputBubbleController::SetBubbleRecognizingMode(int caller_id) { 63 void SpeechInputBubbleController::SetBubbleRecognizingMode(int caller_id) {
58 ProcessRequestInUiThread(caller_id, REQUEST_SET_RECOGNIZING_MODE, 64 ProcessRequestInUiThread(caller_id, REQUEST_SET_RECOGNIZING_MODE,
59 string16(), 0); 65 string16(), 0);
60 } 66 }
61 67
62 void SpeechInputBubbleController::SetBubbleInputVolume(int caller_id, 68 void SpeechInputBubbleController::SetBubbleInputVolume(int caller_id,
63 float volume) { 69 float volume) {
64 ProcessRequestInUiThread(caller_id, REQUEST_SET_INPUT_VOLUME, string16(), 70 ProcessRequestInUiThread(caller_id, REQUEST_SET_INPUT_VOLUME, string16(),
65 volume); 71 volume);
66 } 72 }
67 73
68 void SpeechInputBubbleController::SetBubbleMessage(int caller_id, 74 void SpeechInputBubbleController::SetBubbleMessage(int caller_id,
69 const string16& text) { 75 const string16& text) {
70 ProcessRequestInUiThread(caller_id, REQUEST_SET_MESSAGE, text, 0); 76 ProcessRequestInUiThread(caller_id, REQUEST_SET_MESSAGE, text, 0);
71 } 77 }
72 78
79 void SpeechInputBubbleController::UpdateTabContentsSubscription(
80 int caller_id, ManageSubscriptionAction action) {
81 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
82
83 // If there are any other bubbles existing for the same TabContents, we would
84 // have subscribed to tab close notifications on their behalf and we need to
85 // stay registered. So we don't change the subscription in such cases.
86 TabContents* tab_contents = bubbles_[caller_id]->tab_contents();
87 for (BubbleCallerIdMap::iterator iter = bubbles_.begin();
88 iter != bubbles_.end(); ++iter) {
89 if (iter->second->tab_contents() == tab_contents &&
90 iter->first != caller_id) {
91 // At least one other bubble exists for the same TabContents. So don't
92 // make any change to the subscription.
93 return;
94 }
95 }
96
97 if (action == BUBBLE_ADDED) {
98 registrar_->Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
99 Source<TabContents>(tab_contents));
100 } else {
101 registrar_->Remove(this, NotificationType::TAB_CONTENTS_DESTROYED,
102 Source<TabContents>(tab_contents));
103 }
104 }
105
106 void SpeechInputBubbleController::Observe(NotificationType type,
107 const NotificationSource& source,
108 const NotificationDetails& details) {
109 if (type == NotificationType::TAB_CONTENTS_DESTROYED) {
110 // Cancel all bubbles and active recognition sessions for this tab.
111 TabContents* tab_contents = Source<TabContents>(source).ptr();
112 BubbleCallerIdMap::iterator iter = bubbles_.begin();
113 while (iter != bubbles_.end()) {
114 if (iter->second->tab_contents() == tab_contents) {
115 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
116 NewRunnableMethod(
117 this,
118 &SpeechInputBubbleController::InvokeDelegateButtonClicked,
119 iter->first, SpeechInputBubble::BUTTON_CANCEL));
120 CloseBubble(iter->first);
121 // We expect to have a very small number of items in this map so
122 // redo-ing from start is ok.
123 iter = bubbles_.begin();
124 } else {
125 ++iter;
126 }
127 }
128 } else {
129 NOTREACHED() << "Unknown notification";
130 }
131 }
132
73 void SpeechInputBubbleController::ProcessRequestInUiThread( 133 void SpeechInputBubbleController::ProcessRequestInUiThread(
74 int caller_id, RequestType type, const string16& text, float volume) { 134 int caller_id, RequestType type, const string16& text, float volume) {
75 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 135 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
76 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod( 136 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod(
77 this, &SpeechInputBubbleController::ProcessRequestInUiThread, 137 this, &SpeechInputBubbleController::ProcessRequestInUiThread,
78 caller_id, type, text, volume)); 138 caller_id, type, text, volume));
79 return; 139 return;
80 } 140 }
81 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 141 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
82 // The bubble may have been closed before we got a chance to process this 142 // The bubble may have been closed before we got a chance to process this
(...skipping 19 matching lines...) Expand all
102 break; 162 break;
103 case REQUEST_SET_MESSAGE: 163 case REQUEST_SET_MESSAGE:
104 bubble->SetMessage(text); 164 bubble->SetMessage(text);
105 break; 165 break;
106 case REQUEST_SET_INPUT_VOLUME: 166 case REQUEST_SET_INPUT_VOLUME:
107 bubble->SetInputVolume(volume); 167 bubble->SetInputVolume(volume);
108 break; 168 break;
109 case REQUEST_CLOSE: 169 case REQUEST_CLOSE:
110 if (current_bubble_caller_id_ == caller_id) 170 if (current_bubble_caller_id_ == caller_id)
111 current_bubble_caller_id_ = 0; 171 current_bubble_caller_id_ = 0;
172 UpdateTabContentsSubscription(caller_id, BUBBLE_REMOVED);
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