| Index: chrome/browser/speech/speech_recognition_bubble_controller.cc
|
| diff --git a/chrome/browser/speech/speech_recognition_bubble_controller.cc b/chrome/browser/speech/speech_recognition_bubble_controller.cc
|
| index c03d01921bc06b091392feb3d1e052b0e2b5c7de..fed8a4cc67ca997821bb32e036a4c7984ee1e65c 100644
|
| --- a/chrome/browser/speech/speech_recognition_bubble_controller.cc
|
| +++ b/chrome/browser/speech/speech_recognition_bubble_controller.cc
|
| @@ -10,19 +10,30 @@
|
| #include "content/public/browser/notification_registrar.h"
|
| #include "content/public/browser/notification_source.h"
|
| #include "content/public/browser/notification_types.h"
|
| +#include "content/public/browser/render_process_host.h"
|
| +#include "content/public/browser/render_view_host.h"
|
| #include "content/public/browser/web_contents.h"
|
| -#include "ui/gfx/rect.h"
|
|
|
| using content::BrowserThread;
|
| using content::WebContents;
|
|
|
| +namespace {
|
| +const int kNoBubble = 0;
|
| +}
|
| +
|
| namespace speech {
|
|
|
| SpeechRecognitionBubbleController::SpeechRecognitionBubbleController(
|
| Delegate* delegate)
|
| : delegate_(delegate),
|
| - current_bubble_session_id_(0),
|
| - registrar_(new content::NotificationRegistrar) {
|
| + current_bubble_session_id_(kNoBubble),
|
| + current_bubble_render_process_id_(0),
|
| + current_bubble_render_view_id_(0),
|
| + last_request_issued_(REQUEST_CLOSE) {
|
| +}
|
| +
|
| +SpeechRecognitionBubbleController::~SpeechRecognitionBubbleController() {
|
| + DCHECK_EQ(kNoBubble, current_bubble_session_id_);
|
| }
|
|
|
| void SpeechRecognitionBubbleController::CreateBubble(
|
| @@ -30,216 +41,160 @@ void SpeechRecognitionBubbleController::CreateBubble(
|
| int render_process_id,
|
| int render_view_id,
|
| const gfx::Rect& element_rect) {
|
| - if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
|
| - BrowserThread::PostTask(
|
| - BrowserThread::UI, FROM_HERE,
|
| - base::Bind(&SpeechRecognitionBubbleController::CreateBubble, this,
|
| - session_id, render_process_id, render_view_id,
|
| - element_rect));
|
| - return;
|
| - }
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - WebContents* web_contents = tab_util::GetWebContentsByID(render_process_id,
|
| - render_view_id);
|
| -
|
| - DCHECK_EQ(0u, bubbles_.count(session_id));
|
| - SpeechRecognitionBubble* bubble = SpeechRecognitionBubble::Create(
|
| - web_contents, this, element_rect);
|
| - if (!bubble) {
|
| - // Could be null if tab or display rect were invalid.
|
| - // Simulate the cancel button being clicked to inform the delegate.
|
| - BrowserThread::PostTask(
|
| - BrowserThread::IO, FROM_HERE,
|
| - base::Bind(
|
| - &SpeechRecognitionBubbleController::InvokeDelegateButtonClicked,
|
| - this, session_id, SpeechRecognitionBubble::BUTTON_CANCEL));
|
| - return;
|
| - }
|
| -
|
| - bubbles_[session_id] = bubble;
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + current_bubble_session_id_ = session_id;
|
| + current_bubble_render_process_id_ = render_process_id;
|
| + current_bubble_render_view_id_ = render_view_id;
|
|
|
| - UpdateTabContentsSubscription(session_id, BUBBLE_ADDED);
|
| + UIRequest request(REQUEST_CREATE);
|
| + request.render_process_id = render_process_id;
|
| + request.render_view_id = render_view_id;
|
| + request.element_rect = element_rect;
|
| + ProcessRequestInUiThread(request);
|
| }
|
|
|
| -void SpeechRecognitionBubbleController::SetBubbleWarmUpMode(int session_id) {
|
| - ProcessRequestInUiThread(session_id, REQUEST_SET_WARM_UP_MODE,
|
| - string16(), 0, 0);
|
| +void SpeechRecognitionBubbleController::SetBubbleRecordingMode() {
|
| + ProcessRequestInUiThread(UIRequest(REQUEST_SET_RECORDING_MODE));
|
| }
|
|
|
| -void SpeechRecognitionBubbleController::SetBubbleRecordingMode(int session_id) {
|
| - ProcessRequestInUiThread(session_id, REQUEST_SET_RECORDING_MODE,
|
| - string16(), 0, 0);
|
| +void SpeechRecognitionBubbleController::SetBubbleRecognizingMode() {
|
| + ProcessRequestInUiThread(UIRequest(REQUEST_SET_RECOGNIZING_MODE));
|
| }
|
|
|
| -void SpeechRecognitionBubbleController::SetBubbleRecognizingMode(
|
| - int session_id) {
|
| - ProcessRequestInUiThread(session_id, REQUEST_SET_RECOGNIZING_MODE,
|
| - string16(), 0, 0);
|
| +void SpeechRecognitionBubbleController::SetBubbleMessage(const string16& text) {
|
| + UIRequest request(REQUEST_SET_MESSAGE);
|
| + request.message = text;
|
| + ProcessRequestInUiThread(request);
|
| }
|
|
|
| -void SpeechRecognitionBubbleController::SetBubbleMessage(int session_id,
|
| - const string16& text) {
|
| - ProcessRequestInUiThread(session_id, REQUEST_SET_MESSAGE, text, 0, 0);
|
| +bool SpeechRecognitionBubbleController::IsShowingMessage() const {
|
| + return last_request_issued_ == REQUEST_SET_MESSAGE;
|
| }
|
|
|
| void SpeechRecognitionBubbleController::SetBubbleInputVolume(
|
| - int session_id, float volume, float noise_volume) {
|
| - ProcessRequestInUiThread(session_id, REQUEST_SET_INPUT_VOLUME, string16(),
|
| - volume, noise_volume);
|
| + float volume, float noise_volume) {
|
| + UIRequest request(REQUEST_SET_INPUT_VOLUME);
|
| + request.volume = volume;
|
| + request.noise_volume = noise_volume;
|
| + ProcessRequestInUiThread(request);
|
| }
|
|
|
| -void SpeechRecognitionBubbleController::CloseBubble(int session_id) {
|
| - ProcessRequestInUiThread(session_id, REQUEST_CLOSE, string16(), 0, 0);
|
| +void SpeechRecognitionBubbleController::CloseBubble() {
|
| + current_bubble_session_id_ = kNoBubble;
|
| + ProcessRequestInUiThread(UIRequest(REQUEST_CLOSE));
|
| +}
|
| +
|
| +int SpeechRecognitionBubbleController::GetActiveSessionID() const {
|
| + return current_bubble_session_id_;
|
| +}
|
| +
|
| +bool SpeechRecognitionBubbleController::IsShowingBubbleOn(int render_process_id,
|
| + int render_view_id) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + return (current_bubble_session_id_ != kNoBubble) &&
|
| + (current_bubble_render_process_id_ == render_process_id) &&
|
| + (current_bubble_render_view_id_ == render_view_id);
|
| }
|
|
|
| void SpeechRecognitionBubbleController::InfoBubbleButtonClicked(
|
| SpeechRecognitionBubble::Button button) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - DCHECK(current_bubble_session_id_);
|
| -
|
| BrowserThread::PostTask(
|
| BrowserThread::IO, FROM_HERE,
|
| base::Bind(
|
| &SpeechRecognitionBubbleController::InvokeDelegateButtonClicked,
|
| - this, current_bubble_session_id_, button));
|
| + this, button));
|
| }
|
|
|
| void SpeechRecognitionBubbleController::InfoBubbleFocusChanged() {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - DCHECK(current_bubble_session_id_);
|
| -
|
| - int old_bubble_session_id = current_bubble_session_id_;
|
| - current_bubble_session_id_ = 0;
|
| -
|
| BrowserThread::PostTask(
|
| BrowserThread::IO, FROM_HERE,
|
| base::Bind(
|
| &SpeechRecognitionBubbleController::InvokeDelegateFocusChanged,
|
| - this, old_bubble_session_id));
|
| -}
|
| -
|
| -void SpeechRecognitionBubbleController::Observe(
|
| - int type,
|
| - const content::NotificationSource& source,
|
| - const content::NotificationDetails& details) {
|
| - if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) {
|
| - // Cancel all bubbles and active recognition sessions for this tab.
|
| - WebContents* web_contents = content::Source<WebContents>(source).ptr();
|
| - BubbleSessionIdMap::iterator iter = bubbles_.begin();
|
| - while (iter != bubbles_.end()) {
|
| - if (iter->second->GetWebContents() == web_contents) {
|
| - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
| - base::Bind(
|
| - &SpeechRecognitionBubbleController::InvokeDelegateButtonClicked,
|
| - this, iter->first, SpeechRecognitionBubble::BUTTON_CANCEL));
|
| - CloseBubble(iter->first);
|
| - // We expect to have a very small number of items in this map so
|
| - // redo-ing from start is ok.
|
| - iter = bubbles_.begin();
|
| - } else {
|
| - ++iter;
|
| - }
|
| - }
|
| - } else {
|
| - NOTREACHED() << "Unknown notification";
|
| - }
|
| -}
|
| -
|
| -SpeechRecognitionBubbleController::~SpeechRecognitionBubbleController() {
|
| - DCHECK(bubbles_.empty());
|
| + this));
|
| }
|
|
|
| void SpeechRecognitionBubbleController::InvokeDelegateButtonClicked(
|
| - int session_id, SpeechRecognitionBubble::Button button) {
|
| - delegate_->InfoBubbleButtonClicked(session_id, button);
|
| + SpeechRecognitionBubble::Button button) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + DCHECK_NE(kNoBubble, current_bubble_session_id_);
|
| + delegate_->InfoBubbleButtonClicked(current_bubble_session_id_, button);
|
| }
|
|
|
| -void SpeechRecognitionBubbleController::InvokeDelegateFocusChanged(
|
| - int session_id) {
|
| - delegate_->InfoBubbleFocusChanged(session_id);
|
| +void SpeechRecognitionBubbleController::InvokeDelegateFocusChanged() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + DCHECK_NE(kNoBubble, current_bubble_session_id_);
|
| + delegate_->InfoBubbleFocusChanged(current_bubble_session_id_);
|
| }
|
|
|
| void SpeechRecognitionBubbleController::ProcessRequestInUiThread(
|
| - int session_id, RequestType type, const string16& text, float volume,
|
| - float noise_volume) {
|
| + const UIRequest& request) {
|
| if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
|
| + last_request_issued_ = request.type;
|
| BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
|
| - &SpeechRecognitionBubbleController::ProcessRequestInUiThread, this,
|
| - session_id, type, text, volume, noise_volume));
|
| + &SpeechRecognitionBubbleController::ProcessRequestInUiThread,
|
| + this,
|
| + request));
|
| return;
|
| }
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - // The bubble may have been closed before we got a chance to process this
|
| - // request. So check before proceeding.
|
| - if (!bubbles_.count(session_id))
|
| - return;
|
|
|
| - bool change_active_bubble = (type == REQUEST_SET_WARM_UP_MODE ||
|
| - type == REQUEST_SET_MESSAGE);
|
| - if (change_active_bubble) {
|
| - if (current_bubble_session_id_ && current_bubble_session_id_ != session_id)
|
| - bubbles_[current_bubble_session_id_]->Hide();
|
| - current_bubble_session_id_ = session_id;
|
| - }
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
|
|
| - SpeechRecognitionBubble* bubble = bubbles_[session_id];
|
| - switch (type) {
|
| - case REQUEST_SET_WARM_UP_MODE:
|
| - bubble->SetWarmUpMode();
|
| + switch (request.type) {
|
| + case REQUEST_CREATE:
|
| + bubble_.reset(SpeechRecognitionBubble::Create(
|
| + tab_util::GetWebContentsByID(request.render_process_id,
|
| + request.render_view_id),
|
| + this,
|
| + request.element_rect));
|
| +
|
| + if (!bubble_.get()) {
|
| + // Could be null if tab or display rect were invalid.
|
| + // Simulate the cancel button being clicked to inform the delegate.
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE, base::Bind(
|
| + &SpeechRecognitionBubbleController::InvokeDelegateButtonClicked,
|
| + this, SpeechRecognitionBubble::BUTTON_CANCEL));
|
| + return;
|
| + }
|
| + bubble_->Show();
|
| + bubble_->SetWarmUpMode();
|
| break;
|
| case REQUEST_SET_RECORDING_MODE:
|
| - bubble->SetRecordingMode();
|
| + DCHECK(bubble_.get());
|
| + bubble_->SetRecordingMode();
|
| break;
|
| case REQUEST_SET_RECOGNIZING_MODE:
|
| - bubble->SetRecognizingMode();
|
| + DCHECK(bubble_.get());
|
| + bubble_->SetRecognizingMode();
|
| break;
|
| case REQUEST_SET_MESSAGE:
|
| - bubble->SetMessage(text);
|
| + DCHECK(bubble_.get());
|
| + bubble_->SetMessage(request.message);
|
| break;
|
| case REQUEST_SET_INPUT_VOLUME:
|
| - bubble->SetInputVolume(volume, noise_volume);
|
| + DCHECK(bubble_.get());
|
| + bubble_->SetInputVolume(request.volume, request.noise_volume);
|
| break;
|
| case REQUEST_CLOSE:
|
| - if (current_bubble_session_id_ == session_id)
|
| - current_bubble_session_id_ = 0;
|
| - UpdateTabContentsSubscription(session_id, BUBBLE_REMOVED);
|
| - delete bubble;
|
| - bubbles_.erase(session_id);
|
| + bubble_.reset();
|
| break;
|
| default:
|
| NOTREACHED();
|
| break;
|
| }
|
| -
|
| - if (change_active_bubble)
|
| - bubble->Show();
|
| }
|
|
|
| -void SpeechRecognitionBubbleController::UpdateTabContentsSubscription(
|
| - int session_id, ManageSubscriptionAction action) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| -
|
| - // If there are any other bubbles existing for the same WebContents, we would
|
| - // have subscribed to tab close notifications on their behalf and we need to
|
| - // stay registered. So we don't change the subscription in such cases.
|
| - WebContents* web_contents = bubbles_[session_id]->GetWebContents();
|
| - for (BubbleSessionIdMap::iterator iter = bubbles_.begin();
|
| - iter != bubbles_.end(); ++iter) {
|
| - if (iter->second->GetWebContents() == web_contents &&
|
| - iter->first != session_id) {
|
| - // At least one other bubble exists for the same WebContents. So don't
|
| - // make any change to the subscription.
|
| - return;
|
| - }
|
| - }
|
| +SpeechRecognitionBubbleController::UIRequest::UIRequest(RequestType type_value)
|
| + : type(type_value),
|
| + volume(0.0F),
|
| + noise_volume(0.0F),
|
| + render_process_id(0),
|
| + render_view_id(0) {
|
| +}
|
|
|
| - if (action == BUBBLE_ADDED) {
|
| - registrar_->Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
|
| - content::Source<WebContents>(web_contents));
|
| - } else {
|
| - registrar_->Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
|
| - content::Source<WebContents>(web_contents));
|
| - }
|
| +SpeechRecognitionBubbleController::UIRequest::~UIRequest() {
|
| }
|
|
|
| } // namespace speech
|
|
|