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