15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CHROME_BROWSER_SPEECH_SPEECH_RECOGNITION_BUBBLE_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_BROWSER_SPEECH_SPEECH_RECOGNITION_BUBBLE_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/layout.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SkBitmap; 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SkCanvas; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WebContents; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Canvas; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Rect; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SpeechRecognitionBubble displays a popup info bubble during speech 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// recognition, points to the html element which requested speech recognition 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and shows progress events. The popup is closed by the user clicking anywhere 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// outside the popup window, or by the caller destroying this object. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SpeechRecognitionBubble { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The various buttons which may be part of the bubble. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum Button { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BUTTON_TRY_AGAIN, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BUTTON_CANCEL 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Informs listeners of user actions in the bubble. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class Delegate { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invoked when the user selects a button in the info bubble. The InfoBubble 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is still active and the caller should close it if necessary. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void InfoBubbleButtonClicked(Button button) = 0; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invoked when the user clicks outside the InfoBubble causing it to close. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The InfoBubble window is no longer visible on screen and the caller can 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // free the InfoBubble instance. This callback is not issued if the bubble 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // got closed because the object was destroyed by the caller. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void InfoBubbleFocusChanged() = 0; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~Delegate() { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Factory method to create new instances. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates the bubble, call |Show| to display it on screen. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |web_contents| is the WebContents hosting the page. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |element_rect| is the display bounds of the html element requesting speech 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // recognition (in page coordinates). 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static SpeechRecognitionBubble* Create(content::WebContents* web_contents, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate* delegate, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& element_rect); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is implemented by platform specific code to create the underlying 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bubble window. Not to be called directly by users of this class. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static SpeechRecognitionBubble* CreateNativeBubble( 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::WebContents* web_contents, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate* delegate, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& element_rect); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |Create| uses the currently registered FactoryMethod to create the 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SpeechRecognitionBubble instances. FactoryMethod is intended for testing. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef SpeechRecognitionBubble* (*FactoryMethod)(content::WebContents*, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate*, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect&); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets the factory used by the static method Create. SpeechRecognitionBubble 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // does not take ownership of |factory|. A value of NULL results in a 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SpeechRecognitionBubble being created directly. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(UNIT_TEST) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void set_factory(FactoryMethod factory) { factory_ = factory; } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~SpeechRecognitionBubble() {} 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicates to the user that audio hardware is initializing. If the bubble is 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // hidden, |Show| must be called to make it appear on screen. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetWarmUpMode() = 0; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicates to the user that audio recording is in progress. If the bubble is 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // hidden, |Show| must be called to make it appear on screen. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetRecordingMode() = 0; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicates to the user that recognition is in progress. If the bubble is 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // hidden, |Show| must be called to make it appear on screen. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetRecognizingMode() = 0; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Displays the given string with the 'Try again' and 'Cancel' buttons. If the 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bubble is hidden, |Show| must be called to make it appear on screen. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetMessage(const string16& text) = 0; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Brings up the bubble on screen. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Show() = 0; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Hides the info bubble, resulting in a call to 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |Delegate::InfoBubbleFocusChanged| as well. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Hide() = 0; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Updates and draws the current captured audio volume displayed on screen. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetInputVolume(float volume, float noise_volume) = 0; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the WebContents for which this bubble gets displayed. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual content::WebContents* GetWebContents() = 0; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The horizontal distance between the start of the html widget and the speech 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bubble's arrow. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kBubbleTargetOffsetX; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static FactoryMethod factory_; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Base class for the platform specific bubble implementations, this contains 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the platform independent code for SpeechRecognitionBubble. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SpeechRecognitionBubbleBase : public SpeechRecognitionBubble { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The current display mode of the bubble, useful only for the platform 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // specific implementation. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum DisplayMode { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISPLAY_MODE_WARM_UP, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISPLAY_MODE_RECORDING, 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISPLAY_MODE_RECOGNIZING, 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISPLAY_MODE_MESSAGE 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit SpeechRecognitionBubbleBase(content::WebContents* web_contents); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~SpeechRecognitionBubbleBase(); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SpeechRecognitionBubble methods 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetWarmUpMode() OVERRIDE; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetRecordingMode() OVERRIDE; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetRecognizingMode() OVERRIDE; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetMessage(const string16& text) OVERRIDE; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetInputVolume(float volume, float noise_volume) OVERRIDE; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual content::WebContents* GetWebContents() OVERRIDE; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Updates the platform specific UI layout for the current display mode. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void UpdateLayout() = 0; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Overridden by subclasses to copy |icon_image()| to the screen. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void UpdateImage() = 0; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DisplayMode display_mode() const { return display_mode_; } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& message_text() const { return message_text_; } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia icon_image(); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DoRecognizingAnimationStep(); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DoWarmingUpAnimationStep(); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetImage(const gfx::ImageSkia& image); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DrawVolumeOverlay(SkCanvas* canvas, 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::ImageSkia& image_skia, 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float volume); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Task factory used for animation timer. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WeakPtrFactory<SpeechRecognitionBubbleBase> weak_factory_; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int animation_step_; // Current index/step of the animation. 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DisplayMode display_mode_; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 message_text_; // Text displayed in DISPLAY_MODE_MESSAGE 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The current microphone image with volume level indication. 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SkBitmap> mic_image_; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A temporary buffer image used in creating the above mic image. 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SkBitmap> buffer_image_; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // WebContents in which this this bubble gets displayed. 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::WebContents* web_contents_; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The current image displayed in the bubble's icon widget. 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia icon_image_; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The scale factor used for the web-contents. 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ScaleFactor scale_factor_; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SpeechRecognitionBubbleBase); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This typedef is to workaround the issue with certain versions of 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Visual Studio where it gets confused between multiple Delegate 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// classes and gives a C2500 error. (I saw this error on the try bots - 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the workaround was not needed for my machine). 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef SpeechRecognitionBubble::Delegate SpeechRecognitionBubbleDelegate; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CHROME_BROWSER_SPEECH_SPEECH_RECOGNITION_BUBBLE_H_ 199