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