Home | History | Annotate | Download | only in apps
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef APPS_SHELL_WINDOW_H_
      6 #define APPS_SHELL_WINDOW_H_
      7 
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/memory/weak_ptr.h"
     10 #include "chrome/browser/extensions/extension_icon_image.h"
     11 #include "chrome/browser/extensions/extension_keybinding_registry.h"
     12 #include "chrome/browser/sessions/session_id.h"
     13 #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h"
     14 #include "content/public/browser/notification_observer.h"
     15 #include "content/public/browser/notification_registrar.h"
     16 #include "content/public/browser/web_contents_delegate.h"
     17 #include "content/public/browser/web_contents_observer.h"
     18 #include "content/public/common/console_message_level.h"
     19 #include "ui/base/ui_base_types.h"  // WindowShowState
     20 #include "ui/gfx/image/image.h"
     21 #include "ui/gfx/rect.h"
     22 
     23 class GURL;
     24 class Profile;
     25 class SkRegion;
     26 
     27 namespace content {
     28 class WebContents;
     29 }
     30 
     31 namespace extensions {
     32 class Extension;
     33 class PlatformAppBrowserTest;
     34 class WindowController;
     35 
     36 struct DraggableRegion;
     37 }
     38 
     39 namespace ui {
     40 class BaseWindow;
     41 }
     42 
     43 namespace apps {
     44 
     45 class NativeAppWindow;
     46 
     47 // Manages the web contents for Shell Windows. The implementation for this
     48 // class should create and maintain the WebContents for the window, and handle
     49 // any message passing between the web contents and the extension system or
     50 // native window.
     51 class ShellWindowContents {
     52  public:
     53   ShellWindowContents() {}
     54   virtual ~ShellWindowContents() {}
     55 
     56   // Called to initialize the WebContents, before the app window is created.
     57   virtual void Initialize(Profile* profile, const GURL& url) = 0;
     58 
     59   // Called to load the contents, after the app window is created.
     60   virtual void LoadContents(int32 creator_process_id) = 0;
     61 
     62   // Called when the native window changes.
     63   virtual void NativeWindowChanged(NativeAppWindow* native_app_window) = 0;
     64 
     65   // Called when the native window closes.
     66   virtual void NativeWindowClosed() = 0;
     67 
     68   virtual content::WebContents* GetWebContents() const = 0;
     69 
     70  private:
     71   DISALLOW_COPY_AND_ASSIGN(ShellWindowContents);
     72 };
     73 
     74 // ShellWindow is the type of window used by platform apps. Shell windows
     75 // have a WebContents but none of the chrome of normal browser windows.
     76 class ShellWindow : public content::NotificationObserver,
     77                     public content::WebContentsDelegate,
     78                     public content::WebContentsObserver,
     79                     public web_modal::WebContentsModalDialogManagerDelegate,
     80                     public extensions::ExtensionKeybindingRegistry::Delegate,
     81                     public extensions::IconImage::Observer {
     82  public:
     83   enum WindowType {
     84     WINDOW_TYPE_DEFAULT  = 1 << 0,  // Default shell window.
     85     WINDOW_TYPE_PANEL    = 1 << 1,  // OS controlled panel window (Ash only).
     86     WINDOW_TYPE_V1_PANEL = 1 << 2,  // For apps v1 support in Ash; deprecate
     87                                     // with v1 apps.
     88   };
     89 
     90   enum Frame {
     91     FRAME_CHROME,  // Chrome-style window frame.
     92     FRAME_NONE,  // Frameless window.
     93   };
     94 
     95   enum FullscreenType {
     96     // Not fullscreen.
     97     FULLSCREEN_TYPE_NONE = 0,
     98 
     99     // Fullscreen entered by the app.window api.
    100     FULLSCREEN_TYPE_WINDOW_API = 1 << 0,
    101 
    102     // Fullscreen entered by HTML requestFullscreen().
    103     FULLSCREEN_TYPE_HTML_API = 1 << 1,
    104 
    105     // Fullscreen entered by the OS. ChromeOS uses this type of fullscreen to
    106     // enter immersive fullscreen when the user hits the <F4> key.
    107     FULLSCREEN_TYPE_OS = 1 << 2,
    108 
    109     // Fullscreen mode that could not be exited by the user. ChromeOS uses
    110     // this type of fullscreen to run an app in kiosk mode.
    111     FULLSCREEN_TYPE_FORCED = 1 << 3,
    112   };
    113 
    114   class SizeConstraints {
    115    public:
    116     // The value SizeConstraints uses to represent an unbounded width or height.
    117     // This is an enum so that it can be declared inline here.
    118     enum { kUnboundedSize = 0 };
    119 
    120     SizeConstraints();
    121     SizeConstraints(const gfx::Size& min_size, const gfx::Size& max_size);
    122     ~SizeConstraints();
    123 
    124     // Returns the bounds with its size clamped to the min/max size.
    125     gfx::Size ClampSize(gfx::Size size) const;
    126 
    127     // When gfx::Size is used as a min/max size, a zero represents an unbounded
    128     // component. This method checks whether either component is specified.
    129     // Note we can't use gfx::Size::IsEmpty as it returns true if either width
    130     // or height is zero.
    131     bool HasMinimumSize() const;
    132     bool HasMaximumSize() const;
    133 
    134     // This returns true if all components are specified, and min and max are
    135     // equal.
    136     bool HasFixedSize() const;
    137 
    138     gfx::Size GetMaximumSize() const;
    139     gfx::Size GetMinimumSize() const;
    140 
    141     void set_minimum_size(const gfx::Size& min_size);
    142     void set_maximum_size(const gfx::Size& max_size);
    143 
    144    private:
    145     gfx::Size minimum_size_;
    146     gfx::Size maximum_size_;
    147   };
    148 
    149   struct CreateParams {
    150     CreateParams();
    151     ~CreateParams();
    152 
    153     WindowType window_type;
    154     Frame frame;
    155     bool transparent_background;  // Only supported on ash.
    156 
    157     // Specify the initial content bounds of the window (excluding any window
    158     // decorations). INT_MIN designates 'unspecified' for the position
    159     // components, and 0 for the size components. When unspecified, they should
    160     // be replaced with a default value.
    161     gfx::Rect bounds;
    162 
    163     gfx::Size minimum_size;
    164     gfx::Size maximum_size;
    165 
    166     std::string window_key;
    167 
    168     // The process ID of the process that requested the create.
    169     int32 creator_process_id;
    170 
    171     // Initial state of the window.
    172     ui::WindowShowState state;
    173 
    174     // If true, don't show the window after creation.
    175     bool hidden;
    176 
    177     // If true, the window will be resizable by the user. Defaults to true.
    178     bool resizable;
    179 
    180     // If true, the window will be focused on creation. Defaults to true.
    181     bool focused;
    182 
    183     // If true, the window will stay on top of other windows that are not
    184     // configured to be always on top. Defaults to false.
    185     bool always_on_top;
    186   };
    187 
    188   class Delegate {
    189    public:
    190     virtual ~Delegate();
    191 
    192     // General initialization.
    193     virtual void InitWebContents(content::WebContents* web_contents) = 0;
    194     virtual NativeAppWindow* CreateNativeAppWindow(
    195         ShellWindow* window,
    196         const CreateParams& params) = 0;
    197 
    198     // Link handling.
    199     virtual content::WebContents* OpenURLFromTab(
    200         Profile* profile,
    201         content::WebContents* source,
    202         const content::OpenURLParams& params) = 0;
    203     virtual void AddNewContents(Profile* profile,
    204                                 content::WebContents* new_contents,
    205                                 WindowOpenDisposition disposition,
    206                                 const gfx::Rect& initial_pos,
    207                                 bool user_gesture,
    208                                 bool* was_blocked) = 0;
    209 
    210     // Feature support.
    211     virtual content::ColorChooser* ShowColorChooser(
    212         content::WebContents* web_contents,
    213         SkColor initial_color) = 0;
    214     virtual void RunFileChooser(content::WebContents* tab,
    215                                 const content::FileChooserParams& params) = 0;
    216     virtual void RequestMediaAccessPermission(
    217         content::WebContents* web_contents,
    218         const content::MediaStreamRequest& request,
    219         const content::MediaResponseCallback& callback,
    220       const extensions::Extension* extension) = 0;
    221     virtual int PreferredIconSize() = 0;
    222 
    223     // Web contents modal dialog support.
    224     virtual void SetWebContentsBlocked(content::WebContents* web_contents,
    225                                        bool blocked) = 0;
    226     virtual bool IsWebContentsVisible(content::WebContents* web_contents) = 0;
    227   };
    228 
    229   // Convert draggable regions in raw format to SkRegion format. Caller is
    230   // responsible for deleting the returned SkRegion instance.
    231   static SkRegion* RawDraggableRegionsToSkRegion(
    232       const std::vector<extensions::DraggableRegion>& regions);
    233 
    234   // The constructor and Init methods are public for constructing a ShellWindow
    235   // with a non-standard render interface (e.g. v1 apps using Ash Panels).
    236   // Normally ShellWindow::Create should be used.
    237   // The constructed shell window takes ownership of |delegate|.
    238   ShellWindow(Profile* profile,
    239               Delegate* delegate,
    240               const extensions::Extension* extension);
    241 
    242   // Initializes the render interface, web contents, and native window.
    243   // |shell_window_contents| will become owned by ShellWindow.
    244   void Init(const GURL& url,
    245             ShellWindowContents* shell_window_contents,
    246             const CreateParams& params);
    247 
    248 
    249   const std::string& window_key() const { return window_key_; }
    250   const SessionID& session_id() const { return session_id_; }
    251   const extensions::Extension* extension() const { return extension_; }
    252   const std::string& extension_id() const { return extension_id_; }
    253   content::WebContents* web_contents() const;
    254   WindowType window_type() const { return window_type_; }
    255   bool window_type_is_panel() const {
    256     return (window_type_ == WINDOW_TYPE_PANEL ||
    257             window_type_ == WINDOW_TYPE_V1_PANEL);
    258   }
    259   Profile* profile() const { return profile_; }
    260   const gfx::Image& app_icon() const { return app_icon_; }
    261   const GURL& app_icon_url() { return app_icon_url_; }
    262 
    263   NativeAppWindow* GetBaseWindow();
    264   gfx::NativeWindow GetNativeWindow();
    265 
    266   // Returns the bounds that should be reported to the renderer.
    267   gfx::Rect GetClientBounds() const;
    268 
    269   // NativeAppWindows should call this to determine what the window's title
    270   // is on startup and from within UpdateWindowTitle().
    271   string16 GetTitle() const;
    272 
    273   // Call to notify ShellRegistry and delete the window. Subclasses should
    274   // invoke this method instead of using "delete this".
    275   void OnNativeClose();
    276 
    277   // Should be called by native implementations when the window size, position,
    278   // or minimized/maximized state has changed.
    279   void OnNativeWindowChanged();
    280 
    281   // Should be called by native implementations when the window is activated.
    282   void OnNativeWindowActivated();
    283 
    284   // Specifies a url for the launcher icon.
    285   void SetAppIconUrl(const GURL& icon_url);
    286 
    287   // Set the window shape. Passing a NULL |region| sets the default shape.
    288   void UpdateShape(scoped_ptr<SkRegion> region);
    289 
    290   // Called from the render interface to modify the draggable regions.
    291   void UpdateDraggableRegions(
    292       const std::vector<extensions::DraggableRegion>& regions);
    293 
    294   // Updates the app image to |image|. Called internally from the image loader
    295   // callback. Also called externally for v1 apps using Ash Panels.
    296   void UpdateAppIcon(const gfx::Image& image);
    297 
    298   // Transitions window into fullscreen, maximized, minimized or restores based
    299   // on chrome.app.window API.
    300   void Fullscreen();
    301   void Maximize();
    302   void Minimize();
    303   void Restore();
    304 
    305   // Transitions to OS fullscreen. See FULLSCREEN_TYPE_OS for more details.
    306   void OSFullscreen();
    307 
    308   // Transitions to forced fullscreen. See FULLSCREEN_TYPE_FORCED for more
    309   // details.
    310   void ForcedFullscreen();
    311 
    312   // Set the minimum and maximum size that this window is allowed to be.
    313   void SetMinimumSize(const gfx::Size& min_size);
    314   void SetMaximumSize(const gfx::Size& max_size);
    315 
    316   enum ShowType {
    317     SHOW_ACTIVE,
    318     SHOW_INACTIVE
    319   };
    320 
    321   // Shows the window if its contents have been painted; otherwise flags the
    322   // window to be shown as soon as its contents are painted for the first time.
    323   void Show(ShowType show_type);
    324 
    325   // Hides the window. If the window was previously flagged to be shown on
    326   // first paint, it will be unflagged.
    327   void Hide();
    328 
    329   ShellWindowContents* shell_window_contents_for_test() {
    330     return shell_window_contents_.get();
    331   }
    332 
    333   // Get the size constraints.
    334   const SizeConstraints& size_constraints() const {
    335     return size_constraints_;
    336   }
    337 
    338   // Set whether the window should stay above other windows which are not
    339   // configured to be always-on-top.
    340   void SetAlwaysOnTop(bool always_on_top);
    341 
    342   // Whether the always-on-top property has been set by the chrome.app.window
    343   // API. Note that the actual value of this property in the native app window
    344   // will be false in fullscreen mode.
    345   bool IsAlwaysOnTop() const;
    346 
    347  protected:
    348   virtual ~ShellWindow();
    349 
    350  private:
    351   // PlatformAppBrowserTest needs access to web_contents()
    352   friend class extensions::PlatformAppBrowserTest;
    353 
    354   // content::WebContentsDelegate implementation.
    355   virtual void CloseContents(content::WebContents* contents) OVERRIDE;
    356   virtual bool ShouldSuppressDialogs() OVERRIDE;
    357   virtual content::ColorChooser* OpenColorChooser(
    358       content::WebContents* web_contents,
    359       SkColor color,
    360       const std::vector<content::ColorSuggestion>& suggestions) OVERRIDE;
    361   virtual void RunFileChooser(
    362       content::WebContents* tab,
    363       const content::FileChooserParams& params) OVERRIDE;
    364   virtual bool IsPopupOrPanel(
    365       const content::WebContents* source) const OVERRIDE;
    366   virtual void MoveContents(
    367       content::WebContents* source, const gfx::Rect& pos) OVERRIDE;
    368   virtual void NavigationStateChanged(const content::WebContents* source,
    369                                       unsigned changed_flags) OVERRIDE;
    370   virtual void ToggleFullscreenModeForTab(content::WebContents* source,
    371                                           bool enter_fullscreen) OVERRIDE;
    372   virtual bool IsFullscreenForTabOrPending(
    373       const content::WebContents* source) const OVERRIDE;
    374   virtual void RequestMediaAccessPermission(
    375       content::WebContents* web_contents,
    376       const content::MediaStreamRequest& request,
    377       const content::MediaResponseCallback& callback) OVERRIDE;
    378   virtual content::WebContents* OpenURLFromTab(
    379       content::WebContents* source,
    380       const content::OpenURLParams& params) OVERRIDE;
    381   virtual void AddNewContents(content::WebContents* source,
    382                               content::WebContents* new_contents,
    383                               WindowOpenDisposition disposition,
    384                               const gfx::Rect& initial_pos,
    385                               bool user_gesture,
    386                               bool* was_blocked) OVERRIDE;
    387   virtual bool PreHandleKeyboardEvent(
    388       content::WebContents* source,
    389       const content::NativeWebKeyboardEvent& event,
    390       bool* is_keyboard_shortcut) OVERRIDE;
    391   virtual void HandleKeyboardEvent(
    392       content::WebContents* source,
    393       const content::NativeWebKeyboardEvent& event) OVERRIDE;
    394   virtual void RequestToLockMouse(content::WebContents* web_contents,
    395                                   bool user_gesture,
    396                                   bool last_unlocked_by_target) OVERRIDE;
    397 
    398   // content::WebContentsObserver implementation.
    399   virtual void DidFirstVisuallyNonEmptyPaint(int32 page_id) OVERRIDE;
    400 
    401   // content::NotificationObserver implementation.
    402   virtual void Observe(int type,
    403                        const content::NotificationSource& source,
    404                        const content::NotificationDetails& details) OVERRIDE;
    405 
    406   // web_modal::WebContentsModalDialogManagerDelegate implementation.
    407   virtual void SetWebContentsBlocked(content::WebContents* web_contents,
    408                                      bool blocked) OVERRIDE;
    409   virtual bool IsWebContentsVisible(
    410       content::WebContents* web_contents) OVERRIDE;
    411 
    412   // Helper method to add a message to the renderer's DevTools console.
    413   void AddMessageToDevToolsConsole(content::ConsoleMessageLevel level,
    414                                    const std::string& message);
    415 
    416   // Saves the window geometry/position/screen bounds.
    417   void SaveWindowPosition();
    418 
    419   // Helper method to adjust the cached bounds so that we can make sure it can
    420   // be visible on the screen. See http://crbug.com/145752 .
    421   void AdjustBoundsToBeVisibleOnScreen(
    422       const gfx::Rect& cached_bounds,
    423       const gfx::Rect& cached_screen_bounds,
    424       const gfx::Rect& current_screen_bounds,
    425       const gfx::Size& minimum_size,
    426       gfx::Rect* bounds) const;
    427 
    428   // Loads the appropriate default or cached window bounds and constrains them
    429   // based on screen size and minimum/maximum size. Returns a new CreateParams
    430   // that should be used to create the window.
    431   CreateParams LoadDefaultsAndConstrain(CreateParams params) const;
    432 
    433   // Load the app's image, firing a load state change when loaded.
    434   void UpdateExtensionAppIcon();
    435 
    436   // Called when size_constraints is changed.
    437   void OnSizeConstraintsChanged();
    438 
    439   // Set the fullscreen state in the native app window.
    440   void SetNativeWindowFullscreen(int fullscreen_types);
    441 
    442   // extensions::ExtensionKeybindingRegistry::Delegate implementation.
    443   virtual extensions::ActiveTabPermissionGranter*
    444       GetActiveTabPermissionGranter() OVERRIDE;
    445 
    446   // web_modal::WebContentsModalDialogManagerDelegate implementation.
    447   virtual web_modal::WebContentsModalDialogHost*
    448       GetWebContentsModalDialogHost() OVERRIDE;
    449 
    450   // Callback from web_contents()->DownloadFavicon.
    451   void DidDownloadFavicon(int id,
    452                           int http_status_code,
    453                           const GURL& image_url,
    454                           const std::vector<SkBitmap>& bitmaps,
    455                           const std::vector<gfx::Size>& original_bitmap_sizes);
    456 
    457   // extensions::IconImage::Observer implementation.
    458   virtual void OnExtensionIconImageChanged(
    459       extensions::IconImage* image) OVERRIDE;
    460 
    461   Profile* profile_;  // weak pointer - owned by ProfileManager.
    462   // weak pointer - owned by ExtensionService.
    463   const extensions::Extension* extension_;
    464   const std::string extension_id_;
    465 
    466   // Identifier that is used when saving and restoring geometry for this
    467   // window.
    468   std::string window_key_;
    469 
    470   const SessionID session_id_;
    471   WindowType window_type_;
    472   content::NotificationRegistrar registrar_;
    473 
    474   // Icon shown in the task bar.
    475   gfx::Image app_icon_;
    476 
    477   // Icon URL to be used for setting the app icon. If not empty, app_icon_ will
    478   // be fetched and set using this URL.
    479   GURL app_icon_url_;
    480 
    481   // An object to load the app's icon as an extension resource.
    482   scoped_ptr<extensions::IconImage> app_icon_image_;
    483 
    484   scoped_ptr<NativeAppWindow> native_app_window_;
    485   scoped_ptr<ShellWindowContents> shell_window_contents_;
    486   scoped_ptr<Delegate> delegate_;
    487 
    488   base::WeakPtrFactory<ShellWindow> image_loader_ptr_factory_;
    489 
    490   // Bit field of FullscreenType.
    491   int fullscreen_types_;
    492 
    493   // Size constraints on the window.
    494   SizeConstraints size_constraints_;
    495 
    496   // Show has been called, so the window should be shown once the first visually
    497   // non-empty paint occurs.
    498   bool show_on_first_paint_;
    499 
    500   // The first visually non-empty paint has completed.
    501   bool first_paint_complete_;
    502 
    503   // Whether the delayed Show() call was for an active or inactive window.
    504   ShowType delayed_show_type_;
    505 
    506   // Cache the desired value of the always-on-top property. When windows enter
    507   // fullscreen, this property will be automatically switched off for security
    508   // reasons. It is reinstated when the window exits fullscreen.
    509   bool cached_always_on_top_;
    510 
    511   DISALLOW_COPY_AND_ASSIGN(ShellWindow);
    512 };
    513 
    514 }  // namespace apps
    515 
    516 #endif  // APPS_SHELL_WINDOW_H_
    517