summaryrefslogtreecommitdiffstats
path: root/chrome/browser/speech
diff options
context:
space:
mode:
authorKristian Monsen <kristianm@google.com>2011-05-24 16:24:13 +0100
committerKristian Monsen <kristianm@google.com>2011-05-25 14:13:32 +0100
commit3f50c38dc070f4bb515c1b64450dae14f316474e (patch)
tree29f309f9534e05c47244eedb438fc612578d133b /chrome/browser/speech
parente23bef148f7be2bdf9c3cb2cd3aa5ceebf1190fb (diff)
downloadexternal_chromium-3f50c38dc070f4bb515c1b64450dae14f316474e.zip
external_chromium-3f50c38dc070f4bb515c1b64450dae14f316474e.tar.gz
external_chromium-3f50c38dc070f4bb515c1b64450dae14f316474e.tar.bz2
Merge Chromium at r10.0.634.0: Initial merge by git.
Change-Id: Iac2af492818d119bcc2562eb5fdabf5ab0b6df9c
Diffstat (limited to 'chrome/browser/speech')
-rw-r--r--chrome/browser/speech/speech_input_bubble.cc5
-rw-r--r--chrome/browser/speech/speech_input_bubble.h8
-rw-r--r--chrome/browser/speech/speech_input_bubble_controller.cc63
-rw-r--r--chrome/browser/speech/speech_input_bubble_controller.h28
-rw-r--r--chrome/browser/speech/speech_input_bubble_controller_unittest.cc33
-rw-r--r--chrome/browser/speech/speech_input_bubble_gtk.cc9
-rw-r--r--chrome/browser/speech/speech_input_bubble_mac.mm7
-rw-r--r--chrome/browser/speech/speech_input_bubble_views.cc51
-rw-r--r--chrome/browser/speech/speech_input_dispatcher_host.cc34
-rw-r--r--chrome/browser/speech/speech_input_manager.cc27
-rw-r--r--chrome/browser/speech/speech_input_manager.h4
-rw-r--r--chrome/browser/speech/speech_recognition_request.h5
-rw-r--r--chrome/browser/speech/speech_recognizer.cc2
13 files changed, 197 insertions, 79 deletions
diff --git a/chrome/browser/speech/speech_input_bubble.cc b/chrome/browser/speech/speech_input_bubble.cc
index 655415f..77619e9 100644
--- a/chrome/browser/speech/speech_input_bubble.cc
+++ b/chrome/browser/speech/speech_input_bubble.cc
@@ -32,9 +32,10 @@ SpeechInputBubble* SpeechInputBubble::Create(TabContents* tab_contents,
return CreateNativeBubble(tab_contents, delegate, element_rect);
}
-SpeechInputBubbleBase::SpeechInputBubbleBase()
+SpeechInputBubbleBase::SpeechInputBubbleBase(TabContents* tab_contents)
: ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)),
- display_mode_(DISPLAY_MODE_RECORDING) {
+ display_mode_(DISPLAY_MODE_RECORDING),
+ tab_contents_(tab_contents) {
if (!mic_empty_) { // Static variables.
mic_empty_ = ResourceBundle::GetSharedInstance().GetBitmapNamed(
IDR_SPEECH_INPUT_MIC_EMPTY);
diff --git a/chrome/browser/speech/speech_input_bubble.h b/chrome/browser/speech/speech_input_bubble.h
index 3faabe0..436e6bb 100644
--- a/chrome/browser/speech/speech_input_bubble.h
+++ b/chrome/browser/speech/speech_input_bubble.h
@@ -99,6 +99,9 @@ class SpeechInputBubble {
// Updates the current captured audio volume displayed on screen.
virtual void SetInputVolume(float volume) = 0;
+ // Returns the TabContents for which this bubble gets displayed.
+ virtual TabContents* tab_contents() = 0;
+
// The horizontal distance between the start of the html widget and the speech
// bubble's arrow.
static const int kBubbleTargetOffsetX;
@@ -119,7 +122,7 @@ class SpeechInputBubbleBase : public SpeechInputBubble {
DISPLAY_MODE_MESSAGE
};
- SpeechInputBubbleBase();
+ explicit SpeechInputBubbleBase(TabContents* tab_contents);
virtual ~SpeechInputBubbleBase();
// SpeechInputBubble methods
@@ -127,6 +130,7 @@ class SpeechInputBubbleBase : public SpeechInputBubble {
virtual void SetRecognizingMode();
virtual void SetMessage(const string16& text);
virtual void SetInputVolume(float volume);
+ virtual TabContents* tab_contents() { return tab_contents_; }
protected:
// Updates the platform specific UI layout for the current display mode.
@@ -159,6 +163,8 @@ class SpeechInputBubbleBase : public SpeechInputBubble {
scoped_ptr<SkBitmap> mic_image_;
// A temporary buffer image used in creating the above mic image.
scoped_ptr<SkBitmap> buffer_image_;
+ // TabContents in which this this bubble gets displayed.
+ TabContents* tab_contents_;
static SkBitmap* mic_full_; // Mic image with full volume.
static SkBitmap* mic_empty_; // Mic image with zero volume.
diff --git a/chrome/browser/speech/speech_input_bubble_controller.cc b/chrome/browser/speech/speech_input_bubble_controller.cc
index 682d028..b048589 100644
--- a/chrome/browser/speech/speech_input_bubble_controller.cc
+++ b/chrome/browser/speech/speech_input_bubble_controller.cc
@@ -7,13 +7,17 @@
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_util.h"
+#include "chrome/common/notification_registrar.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/notification_type.h"
#include "gfx/rect.h"
namespace speech_input {
SpeechInputBubbleController::SpeechInputBubbleController(Delegate* delegate)
: delegate_(delegate),
- current_bubble_caller_id_(0) {
+ current_bubble_caller_id_(0),
+ registrar_(new NotificationRegistrar) {
}
SpeechInputBubbleController::~SpeechInputBubbleController() {
@@ -43,6 +47,8 @@ void SpeechInputBubbleController::CreateBubble(int caller_id,
return;
bubbles_[caller_id] = bubble;
+
+ UpdateTabContentsSubscription(caller_id, BUBBLE_ADDED);
}
void SpeechInputBubbleController::CloseBubble(int caller_id) {
@@ -70,6 +76,60 @@ void SpeechInputBubbleController::SetBubbleMessage(int caller_id,
ProcessRequestInUiThread(caller_id, REQUEST_SET_MESSAGE, text, 0);
}
+void SpeechInputBubbleController::UpdateTabContentsSubscription(
+ int caller_id, ManageSubscriptionAction action) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // If there are any other bubbles existing for the same TabContents, 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.
+ TabContents* tab_contents = bubbles_[caller_id]->tab_contents();
+ for (BubbleCallerIdMap::iterator iter = bubbles_.begin();
+ iter != bubbles_.end(); ++iter) {
+ if (iter->second->tab_contents() == tab_contents &&
+ iter->first != caller_id) {
+ // At least one other bubble exists for the same TabContents. So don't
+ // make any change to the subscription.
+ return;
+ }
+ }
+
+ if (action == BUBBLE_ADDED) {
+ registrar_->Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
+ Source<TabContents>(tab_contents));
+ } else {
+ registrar_->Remove(this, NotificationType::TAB_CONTENTS_DESTROYED,
+ Source<TabContents>(tab_contents));
+ }
+}
+
+void SpeechInputBubbleController::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ if (type == NotificationType::TAB_CONTENTS_DESTROYED) {
+ // Cancel all bubbles and active recognition sessions for this tab.
+ TabContents* tab_contents = Source<TabContents>(source).ptr();
+ BubbleCallerIdMap::iterator iter = bubbles_.begin();
+ while (iter != bubbles_.end()) {
+ if (iter->second->tab_contents() == tab_contents) {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &SpeechInputBubbleController::InvokeDelegateButtonClicked,
+ iter->first, SpeechInputBubble::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";
+ }
+}
+
void SpeechInputBubbleController::ProcessRequestInUiThread(
int caller_id, RequestType type, const string16& text, float volume) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
@@ -109,6 +169,7 @@ void SpeechInputBubbleController::ProcessRequestInUiThread(
case REQUEST_CLOSE:
if (current_bubble_caller_id_ == caller_id)
current_bubble_caller_id_ = 0;
+ UpdateTabContentsSubscription(caller_id, BUBBLE_REMOVED);
delete bubble;
bubbles_.erase(caller_id);
break;
diff --git a/chrome/browser/speech/speech_input_bubble_controller.h b/chrome/browser/speech/speech_input_bubble_controller.h
index 0a20333..04c92b5 100644
--- a/chrome/browser/speech/speech_input_bubble_controller.h
+++ b/chrome/browser/speech/speech_input_bubble_controller.h
@@ -11,10 +11,12 @@
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/speech/speech_input_bubble.h"
+#include "chrome/common/notification_observer.h"
namespace gfx {
class Rect;
}
+class NotificationRegistrar;
namespace speech_input {
@@ -25,7 +27,8 @@ namespace speech_input {
// that bubble are reported to the delegate.
class SpeechInputBubbleController
: public base::RefCountedThreadSafe<SpeechInputBubbleController>,
- public SpeechInputBubbleDelegate {
+ public SpeechInputBubbleDelegate,
+ public NotificationObserver {
public:
// All methods of this delegate are called in the IO thread.
class Delegate {
@@ -73,6 +76,11 @@ class SpeechInputBubbleController
virtual void InfoBubbleButtonClicked(SpeechInputBubble::Button button);
virtual void InfoBubbleFocusChanged();
+ // NotificationObserver implementation.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
private:
// The various calls received by this object and handled in the UI thread.
enum RequestType {
@@ -83,6 +91,11 @@ class SpeechInputBubbleController
REQUEST_CLOSE,
};
+ enum ManageSubscriptionAction {
+ BUBBLE_ADDED,
+ BUBBLE_REMOVED
+ };
+
void InvokeDelegateButtonClicked(int caller_id,
SpeechInputBubble::Button button);
void InvokeDelegateFocusChanged(int caller_id);
@@ -91,6 +104,14 @@ class SpeechInputBubbleController
const string16& text,
float volume);
+ // Called whenever a bubble was added to or removed from the list. If the
+ // bubble was being added, this method registers for close notifications with
+ // the TabContents if this was the first bubble for the tab. Similarly if the
+ // bubble was being removed, this method unregisters from TabContents if this
+ // was the last bubble associated with that tab.
+ void UpdateTabContentsSubscription(int caller_id,
+ ManageSubscriptionAction action);
+
// Only accessed in the IO thread.
Delegate* delegate_;
@@ -102,7 +123,10 @@ class SpeechInputBubbleController
// Map of caller-ids to bubble objects. The bubbles are weak pointers owned by
// this object and get destroyed by |CloseBubble|.
- std::map<int, SpeechInputBubble*> bubbles_;
+ typedef std::map<int, SpeechInputBubble*> BubbleCallerIdMap;
+ BubbleCallerIdMap bubbles_;
+
+ scoped_ptr<NotificationRegistrar> registrar_;
};
// This typedef is to workaround the issue with certain versions of
diff --git a/chrome/browser/speech/speech_input_bubble_controller_unittest.cc b/chrome/browser/speech/speech_input_bubble_controller_unittest.cc
index 2ed1f1b..e0ca5ba 100644
--- a/chrome/browser/speech/speech_input_bubble_controller_unittest.cc
+++ b/chrome/browser/speech/speech_input_bubble_controller_unittest.cc
@@ -5,6 +5,8 @@
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/speech/speech_input_bubble_controller.h"
+#include "chrome/test/browser_with_test_window_test.h"
+#include "chrome/test/testing_profile.h"
#include "gfx/rect.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -22,7 +24,10 @@ class MockSpeechInputBubble : public SpeechInputBubbleBase {
BUBBLE_TEST_CLICK_TRY_AGAIN,
};
- MockSpeechInputBubble(TabContents*, Delegate* delegate, const gfx::Rect&) {
+ MockSpeechInputBubble(TabContents* tab_contents,
+ Delegate* delegate,
+ const gfx::Rect&)
+ : SpeechInputBubbleBase(tab_contents) {
VLOG(1) << "MockSpeechInputBubble created";
MessageLoop::current()->PostTask(
FROM_HERE, NewRunnableFunction(&InvokeDelegate, delegate));
@@ -62,12 +67,11 @@ class MockSpeechInputBubble : public SpeechInputBubbleBase {
// The test fixture.
class SpeechInputBubbleControllerTest
: public SpeechInputBubbleControllerDelegate,
- public testing::Test {
+ public BrowserWithTestWindowTest {
public:
SpeechInputBubbleControllerTest()
- : io_loop_(MessageLoop::TYPE_IO),
- ui_thread_(BrowserThread::UI), // constructs a new thread and loop
- io_thread_(BrowserThread::IO, &io_loop_), // resuses main thread loop
+ : BrowserWithTestWindowTest(),
+ io_thread_(BrowserThread::IO), // constructs a new thread and loop
cancel_clicked_(false),
try_again_clicked_(false),
focus_changed_(false),
@@ -91,26 +95,28 @@ class SpeechInputBubbleControllerTest
} else if (button == SpeechInputBubble::BUTTON_TRY_AGAIN) {
try_again_clicked_ = true;
}
- MessageLoop::current()->Quit();
+ message_loop()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
}
virtual void InfoBubbleFocusChanged(int caller_id) {
VLOG(1) << "Received InfoBubbleFocusChanged";
EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
focus_changed_ = true;
- MessageLoop::current()->Quit();
+ message_loop()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
}
// testing::Test methods.
virtual void SetUp() {
+ BrowserWithTestWindowTest::SetUp();
SpeechInputBubble::set_factory(
&SpeechInputBubbleControllerTest::CreateBubble);
- ui_thread_.Start();
+ io_thread_.Start();
}
virtual void TearDown() {
SpeechInputBubble::set_factory(NULL);
- ui_thread_.Stop();
+ io_thread_.Stop();
+ BrowserWithTestWindowTest::TearDown();
}
static void ActivateBubble() {
@@ -132,14 +138,19 @@ class SpeechInputBubbleControllerTest
// active.
MessageLoop::current()->PostTask(FROM_HERE,
NewRunnableFunction(&ActivateBubble));
+
+ // The |tab_contents| parameter would be NULL since the dummy caller id
+ // passed to CreateBubble would not have matched any active tab. So get a
+ // real TabContents pointer from the test fixture and pass that, because
+ // the bubble controller registers for tab close notifications which need
+ // a valid TabContents.
+ tab_contents = test_fixture_->browser()->GetSelectedTabContents();
return new MockSpeechInputBubble(tab_contents, delegate, element_rect);
}
protected:
// The main thread of the test is marked as the IO thread and we create a new
// one for the UI thread.
- MessageLoop io_loop_;
- BrowserThread ui_thread_;
BrowserThread io_thread_;
bool cancel_clicked_;
bool try_again_clicked_;
diff --git a/chrome/browser/speech/speech_input_bubble_gtk.cc b/chrome/browser/speech/speech_input_bubble_gtk.cc
index 2b159bf..eb8b906 100644
--- a/chrome/browser/speech/speech_input_bubble_gtk.cc
+++ b/chrome/browser/speech/speech_input_bubble_gtk.cc
@@ -54,7 +54,6 @@ class SpeechInputBubbleGtk
Delegate* delegate_;
InfoBubbleGtk* info_bubble_;
- TabContents* tab_contents_;
gfx::Rect element_rect_;
bool did_invoke_close_;
@@ -68,9 +67,9 @@ class SpeechInputBubbleGtk
SpeechInputBubbleGtk::SpeechInputBubbleGtk(TabContents* tab_contents,
Delegate* delegate,
const gfx::Rect& element_rect)
- : delegate_(delegate),
+ : SpeechInputBubbleBase(tab_contents),
+ delegate_(delegate),
info_bubble_(NULL),
- tab_contents_(tab_contents),
element_rect_(element_rect),
did_invoke_close_(false),
label_(NULL),
@@ -145,10 +144,10 @@ void SpeechInputBubbleGtk::Show() {
gtk_container_add(GTK_CONTAINER(content), vbox);
GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom(
- tab_contents_->profile());
+ tab_contents()->profile());
gfx::Rect rect(element_rect_.x() + kBubbleTargetOffsetX,
element_rect_.y() + element_rect_.height(), 1, 1);
- info_bubble_ = InfoBubbleGtk::Show(tab_contents_->GetNativeView(),
+ info_bubble_ = InfoBubbleGtk::Show(tab_contents()->GetNativeView(),
&rect,
content,
InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT,
diff --git a/chrome/browser/speech/speech_input_bubble_mac.mm b/chrome/browser/speech/speech_input_bubble_mac.mm
index d4a54f2..912370e 100644
--- a/chrome/browser/speech/speech_input_bubble_mac.mm
+++ b/chrome/browser/speech/speech_input_bubble_mac.mm
@@ -30,7 +30,6 @@ class SpeechInputBubbleImpl : public SpeechInputBubbleBase {
private:
scoped_nsobject<SpeechInputWindowController> window_;
- TabContents* tab_contents_;
Delegate* delegate_;
gfx::Rect element_rect_;
};
@@ -38,7 +37,7 @@ class SpeechInputBubbleImpl : public SpeechInputBubbleBase {
SpeechInputBubbleImpl::SpeechInputBubbleImpl(TabContents* tab_contents,
Delegate* delegate,
const gfx::Rect& element_rect)
- : tab_contents_(tab_contents),
+ : SpeechInputBubbleBase(tab_contents),
delegate_(delegate),
element_rect_(element_rect) {
}
@@ -62,7 +61,7 @@ void SpeechInputBubbleImpl::Show() {
// Find the screen coordinates for the given tab and position the bubble's
// arrow anchor point inside that to point at the bottom-left of the html
// input element rect.
- gfx::NativeView view = tab_contents_->view()->GetNativeView();
+ gfx::NativeView view = tab_contents()->view()->GetNativeView();
NSRect tab_bounds = [view bounds];
NSPoint anchor = NSMakePoint(
tab_bounds.origin.x + element_rect_.x() + kBubbleTargetOffsetX,
@@ -72,7 +71,7 @@ void SpeechInputBubbleImpl::Show() {
anchor = [[view window] convertBaseToScreen:anchor];
window_.reset([[SpeechInputWindowController alloc]
- initWithParentWindow:tab_contents_->view()->GetTopLevelNativeWindow()
+ initWithParentWindow:tab_contents()->view()->GetTopLevelNativeWindow()
delegate:delegate_
anchoredAt:anchor]);
diff --git a/chrome/browser/speech/speech_input_bubble_views.cc b/chrome/browser/speech/speech_input_bubble_views.cc
index 83ccad0..2140ef4 100644
--- a/chrome/browser/speech/speech_input_bubble_views.cc
+++ b/chrome/browser/speech/speech_input_bubble_views.cc
@@ -13,10 +13,6 @@
#include "chrome/browser/tab_contents/tab_contents_view.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/views/info_bubble.h"
-#include "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
-#include "chrome/common/notification_source.h"
-#include "chrome/common/notification_type.h"
#include "gfx/canvas.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
@@ -66,7 +62,7 @@ ContentView::ContentView(SpeechInputBubbleDelegate* delegate)
const gfx::Font& font = rb.GetFont(ResourceBundle::MediumFont);
heading_ = new views::Label(
- l10n_util::GetString(IDS_SPEECH_INPUT_BUBBLE_HEADING));
+ UTF16ToWide(l10n_util::GetStringUTF16(IDS_SPEECH_INPUT_BUBBLE_HEADING)));
heading_->SetFont(font);
heading_->SetHorizontalAlignment(views::Label::ALIGN_CENTER);
AddChildView(heading_);
@@ -83,12 +79,14 @@ ContentView::ContentView(SpeechInputBubbleDelegate* delegate)
icon_->SetHorizontalAlignment(views::ImageView::CENTER);
AddChildView(icon_);
- cancel_ = new views::NativeButton(this, l10n_util::GetString(IDS_CANCEL));
+ cancel_ = new views::NativeButton(
+ this,
+ UTF16ToWide(l10n_util::GetStringUTF16(IDS_CANCEL)));
AddChildView(cancel_);
try_again_ = new views::NativeButton(
this,
- l10n_util::GetString(IDS_SPEECH_INPUT_TRY_AGAIN));
+ UTF16ToWide(l10n_util::GetStringUTF16(IDS_SPEECH_INPUT_TRY_AGAIN)));
AddChildView(try_again_);
}
@@ -103,11 +101,13 @@ void ContentView::UpdateLayout(SpeechInputBubbleBase::DisplayMode mode,
if (mode == SpeechInputBubbleBase::DISPLAY_MODE_MESSAGE) {
message_->SetText(UTF16ToWideHack(message_text));
} else if (mode == SpeechInputBubbleBase::DISPLAY_MODE_RECORDING) {
- heading_->SetText(l10n_util::GetString(IDS_SPEECH_INPUT_BUBBLE_HEADING));
+ heading_->SetText(UTF16ToWide(
+ l10n_util::GetStringUTF16(IDS_SPEECH_INPUT_BUBBLE_HEADING)));
icon_->SetImage(*ResourceBundle::GetSharedInstance().GetBitmapNamed(
IDR_SPEECH_INPUT_MIC_EMPTY));
} else {
- heading_->SetText(l10n_util::GetString(IDS_SPEECH_INPUT_BUBBLE_WORKING));
+ heading_->SetText(UTF16ToWide(
+ l10n_util::GetStringUTF16(IDS_SPEECH_INPUT_BUBBLE_WORKING)));
}
}
@@ -196,8 +196,7 @@ void ContentView::Layout() {
// Implementation of SpeechInputBubble.
class SpeechInputBubbleImpl
: public SpeechInputBubbleBase,
- public InfoBubbleDelegate,
- public NotificationObserver {
+ public InfoBubbleDelegate {
public:
SpeechInputBubbleImpl(TabContents* tab_contents,
Delegate* delegate,
@@ -216,11 +215,6 @@ class SpeechInputBubbleImpl
// |element_rect| is the html element's bounds in page coordinates.
gfx::Rect GetInfoBubbleTarget(const gfx::Rect& element_rect);
- // NotificationObserver implementation.
- virtual void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details);
-
// InfoBubbleDelegate
virtual void InfoBubbleClosing(InfoBubble* info_bubble,
bool closed_by_escape);
@@ -230,9 +224,7 @@ class SpeechInputBubbleImpl
private:
Delegate* delegate_;
InfoBubble* info_bubble_;
- TabContents* tab_contents_;
ContentView* bubble_content_;
- NotificationRegistrar registrar_;
gfx::Rect element_rect_;
// Set to true if the object is being destroyed normally instead of the
@@ -245,9 +237,9 @@ class SpeechInputBubbleImpl
SpeechInputBubbleImpl::SpeechInputBubbleImpl(TabContents* tab_contents,
Delegate* delegate,
const gfx::Rect& element_rect)
- : delegate_(delegate),
+ : SpeechInputBubbleBase(tab_contents),
+ delegate_(delegate),
info_bubble_(NULL),
- tab_contents_(tab_contents),
bubble_content_(NULL),
element_rect_(element_rect),
did_invoke_close_(false) {
@@ -261,26 +253,14 @@ SpeechInputBubbleImpl::~SpeechInputBubbleImpl() {
gfx::Rect SpeechInputBubbleImpl::GetInfoBubbleTarget(
const gfx::Rect& element_rect) {
gfx::Rect container_rect;
- tab_contents_->GetContainerBounds(&container_rect);
+ tab_contents()->GetContainerBounds(&container_rect);
return gfx::Rect(
container_rect.x() + element_rect.x() + kBubbleTargetOffsetX,
container_rect.y() + element_rect.y() + element_rect.height(), 1, 1);
}
-void SpeechInputBubbleImpl::Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- if (type == NotificationType::TAB_CONTENTS_DESTROYED) {
- delegate_->InfoBubbleButtonClicked(SpeechInputBubble::BUTTON_CANCEL);
- } else {
- NOTREACHED() << "Unknown notification";
- }
-}
-
void SpeechInputBubbleImpl::InfoBubbleClosing(InfoBubble* info_bubble,
bool closed_by_escape) {
- registrar_.Remove(this, NotificationType::TAB_CONTENTS_DESTROYED,
- Source<TabContents>(tab_contents_));
info_bubble_ = NULL;
bubble_content_ = NULL;
if (!did_invoke_close_)
@@ -303,7 +283,7 @@ void SpeechInputBubbleImpl::Show() {
UpdateLayout();
views::Widget* parent = views::Widget::GetWidgetFromNativeWindow(
- tab_contents_->view()->GetTopLevelNativeWindow());
+ tab_contents()->view()->GetTopLevelNativeWindow());
info_bubble_ = InfoBubble::Show(parent,
GetInfoBubbleTarget(element_rect_),
BubbleBorder::TOP_LEFT, bubble_content_,
@@ -315,9 +295,6 @@ void SpeechInputBubbleImpl::Show() {
// to end so the caller can manage this object's life cycle like a normal
// stack based or member variable object.
info_bubble_->set_fade_away_on_close(false);
-
- registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
- Source<TabContents>(tab_contents_));
}
void SpeechInputBubbleImpl::Hide() {
diff --git a/chrome/browser/speech/speech_input_dispatcher_host.cc b/chrome/browser/speech/speech_input_dispatcher_host.cc
index f1abebf..50b9aec 100644
--- a/chrome/browser/speech/speech_input_dispatcher_host.cc
+++ b/chrome/browser/speech/speech_input_dispatcher_host.cc
@@ -121,17 +121,29 @@ SpeechInputManager* SpeechInputDispatcherHost::manager() {
bool SpeechInputDispatcherHost::OnMessageReceived(
const IPC::Message& message, bool* message_was_ok) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP_EX(SpeechInputDispatcherHost, message, *message_was_ok)
- IPC_MESSAGE_HANDLER(ViewHostMsg_SpeechInput_StartRecognition,
- OnStartRecognition)
- IPC_MESSAGE_HANDLER(ViewHostMsg_SpeechInput_CancelRecognition,
- OnCancelRecognition)
- IPC_MESSAGE_HANDLER(ViewHostMsg_SpeechInput_StopRecording,
- OnStopRecording)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
+
+ uint32 message_type = message.type();
+ if (message_type == ViewHostMsg_SpeechInput_StartRecognition::ID ||
+ message_type == ViewHostMsg_SpeechInput_CancelRecognition::ID ||
+ message_type == ViewHostMsg_SpeechInput_StopRecording::ID) {
+ if (!SpeechInputManager::IsFeatureEnabled()) {
+ *message_was_ok = false;
+ return true;
+ }
+
+ IPC_BEGIN_MESSAGE_MAP_EX(SpeechInputDispatcherHost, message,
+ *message_was_ok)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_SpeechInput_StartRecognition,
+ OnStartRecognition)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_SpeechInput_CancelRecognition,
+ OnCancelRecognition)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_SpeechInput_StopRecording,
+ OnStopRecording)
+ IPC_END_MESSAGE_MAP()
+ return true;
+ }
+
+ return false;
}
void SpeechInputDispatcherHost::OnStartRecognition(
diff --git a/chrome/browser/speech/speech_input_manager.cc b/chrome/browser/speech/speech_input_manager.cc
index b370da4..25f0550 100644
--- a/chrome/browser/speech/speech_input_manager.cc
+++ b/chrome/browser/speech/speech_input_manager.cc
@@ -8,16 +8,20 @@
#include <string>
#include "app/l10n_util.h"
+#include "base/command_line.h"
+#include "base/lazy_instance.h"
#include "base/lock.h"
#include "base/ref_counted.h"
-#include "base/lazy_instance.h"
+#include "base/threading/thread_restrictions.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/platform_util.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/speech/speech_input_bubble_controller.h"
#include "chrome/browser/speech/speech_recognizer.h"
#include "chrome/browser/tab_contents/infobar_delegate.h"
#include "chrome/browser/tab_contents/tab_util.h"
+#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "grit/generated_resources.h"
#include "media/audio/audio_manager.h"
@@ -135,7 +139,6 @@ class SpeechInputManagerImpl : public SpeechInputManager,
// Starts/restarts recognition for an existing request.
void StartRecognitionForRequest(int caller_id);
- SpeechInputManagerDelegate* delegate_;
typedef std::map<int, SpeechInputRequest> SpeechRecognizerMap;
SpeechRecognizerMap requests_;
int recording_caller_id_;
@@ -150,6 +153,26 @@ SpeechInputManager* SpeechInputManager::Get() {
return g_speech_input_manager_impl.Pointer();
}
+bool SpeechInputManager::IsFeatureEnabled() {
+ bool enabled = true;
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+
+ if (command_line.HasSwitch(switches::kDisableSpeechInput)) {
+ enabled = false;
+#if defined(GOOGLE_CHROME_BUILD)
+ } else if (!command_line.HasSwitch(switches::kEnableSpeechInput)) {
+ // We need to evaluate whether IO is OK here. http://crbug.com/63335.
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+ // Official Chrome builds have speech input enabled by default only in the
+ // dev channel.
+ std::string channel = platform_util::GetVersionStringModifier();
+ enabled = (channel == "dev");
+#endif
+ }
+
+ return enabled;
+}
+
SpeechInputManagerImpl::SpeechInputManagerImpl()
: recording_caller_id_(0),
bubble_controller_(new SpeechInputBubbleController(
diff --git a/chrome/browser/speech/speech_input_manager.h b/chrome/browser/speech/speech_input_manager.h
index be9779f..ffeaba0 100644
--- a/chrome/browser/speech/speech_input_manager.h
+++ b/chrome/browser/speech/speech_input_manager.h
@@ -32,6 +32,10 @@ class SpeechInputManager {
virtual ~Delegate() {}
};
+ // Whether the speech input feature is enabled, based on the browser channel
+ // information and command line flags.
+ static bool IsFeatureEnabled();
+
// Factory method to access the singleton. We have this method here instead of
// using Singleton<> directly in the calling code to aid tests in injection
// mocks.
diff --git a/chrome/browser/speech/speech_recognition_request.h b/chrome/browser/speech/speech_recognition_request.h
index d6e9566..c12fc4d 100644
--- a/chrome/browser/speech/speech_recognition_request.h
+++ b/chrome/browser/speech/speech_recognition_request.h
@@ -1,9 +1,10 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
#ifndef CHROME_BROWSER_SPEECH_SPEECH_RECOGNITION_REQUEST_H_
#define CHROME_BROWSER_SPEECH_SPEECH_RECOGNITION_REQUEST_H_
+#pragma once
#include <string>
#include "base/basictypes.h"
@@ -55,7 +56,7 @@ class SpeechRecognitionRequest : public URLFetcher::Delegate {
// URLFetcher::Delegate methods.
virtual void OnURLFetchComplete(const URLFetcher* source,
const GURL& url,
- const URLRequestStatus& status,
+ const net::URLRequestStatus& status,
int response_code,
const ResponseCookies& cookies,
const std::string& data);
diff --git a/chrome/browser/speech/speech_recognizer.cc b/chrome/browser/speech/speech_recognizer.cc
index 3140d46..277393c 100644
--- a/chrome/browser/speech/speech_recognizer.cc
+++ b/chrome/browser/speech/speech_recognizer.cc
@@ -10,7 +10,7 @@
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/net/url_request_context_getter.h"
-#include "third_party/speex/include/speex/speex.h"
+#include "third_party/speex/speex.h"
using media::AudioInputController;
using std::list;