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