Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(300)

Unified Diff: apps/app_window.cc

Issue 494033002: Move AppWindow to extensions (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove unneeded include in chrome_shell_delegate.cc Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « apps/app_window.h ('k') | apps/app_window_browsertest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: apps/app_window.cc
diff --git a/apps/app_window.cc b/apps/app_window.cc
deleted file mode 100644
index 7fd02cd87da22a5364fef9f72d601ad882339ce0..0000000000000000000000000000000000000000
--- a/apps/app_window.cc
+++ /dev/null
@@ -1,1099 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "apps/app_window.h"
-
-#include <algorithm>
-#include <string>
-#include <vector>
-
-#include "apps/app_window_registry.h"
-#include "apps/ui/apps_client.h"
-#include "base/command_line.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/values.h"
-#include "components/web_modal/web_contents_modal_dialog_manager.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/invalidate_type.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
-#include "content/public/browser/notification_types.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/resource_dispatcher_host.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/media_stream_request.h"
-#include "extensions/browser/app_window/app_delegate.h"
-#include "extensions/browser/app_window/app_web_contents_helper.h"
-#include "extensions/browser/app_window/app_window_geometry_cache.h"
-#include "extensions/browser/app_window/native_app_window.h"
-#include "extensions/browser/app_window/size_constraints.h"
-#include "extensions/browser/extension_registry.h"
-#include "extensions/browser/extension_system.h"
-#include "extensions/browser/extensions_browser_client.h"
-#include "extensions/browser/notification_types.h"
-#include "extensions/browser/process_manager.h"
-#include "extensions/browser/suggest_permission_util.h"
-#include "extensions/browser/view_type_utils.h"
-#include "extensions/common/draggable_region.h"
-#include "extensions/common/extension.h"
-#include "extensions/common/manifest_handlers/icons_handler.h"
-#include "extensions/common/permissions/permissions_data.h"
-#include "extensions/common/switches.h"
-#include "third_party/skia/include/core/SkRegion.h"
-#include "ui/gfx/screen.h"
-
-#if !defined(OS_MACOSX)
-#include "base/prefs/pref_service.h"
-#include "extensions/browser/pref_names.h"
-#endif
-
-using content::BrowserContext;
-using content::ConsoleMessageLevel;
-using content::WebContents;
-using extensions::APIPermission;
-using extensions::NativeAppWindow;
-using web_modal::WebContentsModalDialogHost;
-using web_modal::WebContentsModalDialogManager;
-
-namespace apps {
-
-namespace {
-
-const int kDefaultWidth = 512;
-const int kDefaultHeight = 384;
-
-void SetConstraintProperty(const std::string& name,
- int value,
- base::DictionaryValue* bounds_properties) {
- if (value != extensions::SizeConstraints::kUnboundedSize)
- bounds_properties->SetInteger(name, value);
- else
- bounds_properties->Set(name, base::Value::CreateNullValue());
-}
-
-void SetBoundsProperties(const gfx::Rect& bounds,
- const gfx::Size& min_size,
- const gfx::Size& max_size,
- const std::string& bounds_name,
- base::DictionaryValue* window_properties) {
- scoped_ptr<base::DictionaryValue> bounds_properties(
- new base::DictionaryValue());
-
- bounds_properties->SetInteger("left", bounds.x());
- bounds_properties->SetInteger("top", bounds.y());
- bounds_properties->SetInteger("width", bounds.width());
- bounds_properties->SetInteger("height", bounds.height());
-
- SetConstraintProperty("minWidth", min_size.width(), bounds_properties.get());
- SetConstraintProperty(
- "minHeight", min_size.height(), bounds_properties.get());
- SetConstraintProperty("maxWidth", max_size.width(), bounds_properties.get());
- SetConstraintProperty(
- "maxHeight", max_size.height(), bounds_properties.get());
-
- window_properties->Set(bounds_name, bounds_properties.release());
-}
-
-// Combines the constraints of the content and window, and returns constraints
-// for the window.
-gfx::Size GetCombinedWindowConstraints(const gfx::Size& window_constraints,
- const gfx::Size& content_constraints,
- const gfx::Insets& frame_insets) {
- gfx::Size combined_constraints(window_constraints);
- if (content_constraints.width() > 0) {
- combined_constraints.set_width(
- content_constraints.width() + frame_insets.width());
- }
- if (content_constraints.height() > 0) {
- combined_constraints.set_height(
- content_constraints.height() + frame_insets.height());
- }
- return combined_constraints;
-}
-
-// Combines the constraints of the content and window, and returns constraints
-// for the content.
-gfx::Size GetCombinedContentConstraints(const gfx::Size& window_constraints,
- const gfx::Size& content_constraints,
- const gfx::Insets& frame_insets) {
- gfx::Size combined_constraints(content_constraints);
- if (window_constraints.width() > 0) {
- combined_constraints.set_width(
- std::max(0, window_constraints.width() - frame_insets.width()));
- }
- if (window_constraints.height() > 0) {
- combined_constraints.set_height(
- std::max(0, window_constraints.height() - frame_insets.height()));
- }
- return combined_constraints;
-}
-
-} // namespace
-
-// AppWindow::BoundsSpecification
-
-const int AppWindow::BoundsSpecification::kUnspecifiedPosition = INT_MIN;
-
-AppWindow::BoundsSpecification::BoundsSpecification()
- : bounds(kUnspecifiedPosition, kUnspecifiedPosition, 0, 0) {}
-
-AppWindow::BoundsSpecification::~BoundsSpecification() {}
-
-void AppWindow::BoundsSpecification::ResetBounds() {
- bounds.SetRect(kUnspecifiedPosition, kUnspecifiedPosition, 0, 0);
-}
-
-// AppWindow::CreateParams
-
-AppWindow::CreateParams::CreateParams()
- : window_type(AppWindow::WINDOW_TYPE_DEFAULT),
- frame(AppWindow::FRAME_CHROME),
- has_frame_color(false),
- active_frame_color(SK_ColorBLACK),
- inactive_frame_color(SK_ColorBLACK),
- alpha_enabled(false),
- creator_process_id(0),
- state(ui::SHOW_STATE_DEFAULT),
- hidden(false),
- resizable(true),
- focused(true),
- always_on_top(false) {
-}
-
-AppWindow::CreateParams::~CreateParams() {}
-
-gfx::Rect AppWindow::CreateParams::GetInitialWindowBounds(
- const gfx::Insets& frame_insets) const {
- // Combine into a single window bounds.
- gfx::Rect combined_bounds(window_spec.bounds);
- if (content_spec.bounds.x() != BoundsSpecification::kUnspecifiedPosition)
- combined_bounds.set_x(content_spec.bounds.x() - frame_insets.left());
- if (content_spec.bounds.y() != BoundsSpecification::kUnspecifiedPosition)
- combined_bounds.set_y(content_spec.bounds.y() - frame_insets.top());
- if (content_spec.bounds.width() > 0) {
- combined_bounds.set_width(
- content_spec.bounds.width() + frame_insets.width());
- }
- if (content_spec.bounds.height() > 0) {
- combined_bounds.set_height(
- content_spec.bounds.height() + frame_insets.height());
- }
-
- // Constrain the bounds.
- extensions::SizeConstraints constraints(
- GetCombinedWindowConstraints(
- window_spec.minimum_size, content_spec.minimum_size, frame_insets),
- GetCombinedWindowConstraints(
- window_spec.maximum_size, content_spec.maximum_size, frame_insets));
- combined_bounds.set_size(constraints.ClampSize(combined_bounds.size()));
-
- return combined_bounds;
-}
-
-gfx::Size AppWindow::CreateParams::GetContentMinimumSize(
- const gfx::Insets& frame_insets) const {
- return GetCombinedContentConstraints(window_spec.minimum_size,
- content_spec.minimum_size,
- frame_insets);
-}
-
-gfx::Size AppWindow::CreateParams::GetContentMaximumSize(
- const gfx::Insets& frame_insets) const {
- return GetCombinedContentConstraints(window_spec.maximum_size,
- content_spec.maximum_size,
- frame_insets);
-}
-
-gfx::Size AppWindow::CreateParams::GetWindowMinimumSize(
- const gfx::Insets& frame_insets) const {
- return GetCombinedWindowConstraints(window_spec.minimum_size,
- content_spec.minimum_size,
- frame_insets);
-}
-
-gfx::Size AppWindow::CreateParams::GetWindowMaximumSize(
- const gfx::Insets& frame_insets) const {
- return GetCombinedWindowConstraints(window_spec.maximum_size,
- content_spec.maximum_size,
- frame_insets);
-}
-
-// AppWindow
-
-AppWindow::AppWindow(BrowserContext* context,
- extensions::AppDelegate* app_delegate,
- const extensions::Extension* extension)
- : browser_context_(context),
- extension_id_(extension->id()),
- window_type_(WINDOW_TYPE_DEFAULT),
- app_delegate_(app_delegate),
- image_loader_ptr_factory_(this),
- fullscreen_types_(FULLSCREEN_TYPE_NONE),
- show_on_first_paint_(false),
- first_paint_complete_(false),
- has_been_shown_(false),
- can_send_events_(false),
- is_hidden_(false),
- cached_always_on_top_(false),
- requested_alpha_enabled_(false) {
- extensions::ExtensionsBrowserClient* client =
- extensions::ExtensionsBrowserClient::Get();
- CHECK(!client->IsGuestSession(context) || context->IsOffTheRecord())
- << "Only off the record window may be opened in the guest mode.";
-}
-
-void AppWindow::Init(const GURL& url,
- AppWindowContents* app_window_contents,
- const CreateParams& params) {
- // Initialize the render interface and web contents
- app_window_contents_.reset(app_window_contents);
- app_window_contents_->Initialize(browser_context(), url);
- WebContents* web_contents = app_window_contents_->GetWebContents();
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- extensions::switches::kEnableAppsShowOnFirstPaint)) {
- content::WebContentsObserver::Observe(web_contents);
- }
- app_delegate_->InitWebContents(web_contents);
-
- WebContentsModalDialogManager::CreateForWebContents(web_contents);
-
- web_contents->SetDelegate(this);
- WebContentsModalDialogManager::FromWebContents(web_contents)
- ->SetDelegate(this);
- extensions::SetViewType(web_contents, extensions::VIEW_TYPE_APP_WINDOW);
-
- // Initialize the window
- CreateParams new_params = LoadDefaults(params);
- window_type_ = new_params.window_type;
- window_key_ = new_params.window_key;
-
- // Windows cannot be always-on-top in fullscreen mode for security reasons.
- cached_always_on_top_ = new_params.always_on_top;
- if (new_params.state == ui::SHOW_STATE_FULLSCREEN)
- new_params.always_on_top = false;
-
- requested_alpha_enabled_ = new_params.alpha_enabled;
-
- AppsClient* apps_client = AppsClient::Get();
- native_app_window_.reset(
- apps_client->CreateNativeAppWindow(this, new_params));
-
- helper_.reset(new extensions::AppWebContentsHelper(
- browser_context_, extension_id_, web_contents, app_delegate_.get()));
-
- popup_manager_.reset(
- new web_modal::PopupManager(GetWebContentsModalDialogHost()));
- popup_manager_->RegisterWith(web_contents);
-
- // Prevent the browser process from shutting down while this window exists.
- apps_client->IncrementKeepAliveCount();
- UpdateExtensionAppIcon();
- AppWindowRegistry::Get(browser_context_)->AddAppWindow(this);
-
- if (new_params.hidden) {
- // Although the window starts hidden by default, calling Hide() here
- // notifies observers of the window being hidden.
- Hide();
- } else {
- // Panels are not activated by default.
- Show(window_type_is_panel() || !new_params.focused ? SHOW_INACTIVE
- : SHOW_ACTIVE);
- }
-
- if (new_params.state == ui::SHOW_STATE_FULLSCREEN)
- Fullscreen();
- else if (new_params.state == ui::SHOW_STATE_MAXIMIZED)
- Maximize();
- else if (new_params.state == ui::SHOW_STATE_MINIMIZED)
- Minimize();
-
- OnNativeWindowChanged();
-
- // When the render view host is changed, the native window needs to know
- // about it in case it has any setup to do to make the renderer appear
- // properly. In particular, on Windows, the view's clickthrough region needs
- // to be set.
- extensions::ExtensionsBrowserClient* client =
- extensions::ExtensionsBrowserClient::Get();
- registrar_.Add(this,
- extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
- content::Source<content::BrowserContext>(
- client->GetOriginalContext(browser_context_)));
- // Update the app menu if an ephemeral app becomes installed.
- registrar_.Add(
- this,
- extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
- content::Source<content::BrowserContext>(
- client->GetOriginalContext(browser_context_)));
-
- // Close when the browser process is exiting.
- app_delegate_->SetTerminatingCallback(
- base::Bind(&NativeAppWindow::Close,
- base::Unretained(native_app_window_.get())));
-
- app_window_contents_->LoadContents(new_params.creator_process_id);
-
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- extensions::switches::kEnableAppsShowOnFirstPaint)) {
- // We want to show the window only when the content has been painted. For
- // that to happen, we need to define a size for the content, otherwise the
- // layout will happen in a 0x0 area.
- gfx::Insets frame_insets = native_app_window_->GetFrameInsets();
- gfx::Rect initial_bounds = new_params.GetInitialWindowBounds(frame_insets);
- initial_bounds.Inset(frame_insets);
- app_delegate_->ResizeWebContents(web_contents, initial_bounds.size());
- }
-}
-
-AppWindow::~AppWindow() {
- // Unregister now to prevent getting notified if we're the last window open.
- app_delegate_->SetTerminatingCallback(base::Closure());
-
- // Remove shutdown prevention.
- AppsClient::Get()->DecrementKeepAliveCount();
-}
-
-void AppWindow::RequestMediaAccessPermission(
- content::WebContents* web_contents,
- const content::MediaStreamRequest& request,
- const content::MediaResponseCallback& callback) {
- DCHECK_EQ(AppWindow::web_contents(), web_contents);
- helper_->RequestMediaAccessPermission(request, callback);
-}
-
-WebContents* AppWindow::OpenURLFromTab(WebContents* source,
- const content::OpenURLParams& params) {
- DCHECK_EQ(web_contents(), source);
- return helper_->OpenURLFromTab(params);
-}
-
-void AppWindow::AddNewContents(WebContents* source,
- WebContents* new_contents,
- WindowOpenDisposition disposition,
- const gfx::Rect& initial_pos,
- bool user_gesture,
- bool* was_blocked) {
- DCHECK(new_contents->GetBrowserContext() == browser_context_);
- app_delegate_->AddNewContents(browser_context_,
- new_contents,
- disposition,
- initial_pos,
- user_gesture,
- was_blocked);
-}
-
-bool AppWindow::PreHandleKeyboardEvent(
- content::WebContents* source,
- const content::NativeWebKeyboardEvent& event,
- bool* is_keyboard_shortcut) {
- const extensions::Extension* extension = GetExtension();
- if (!extension)
- return false;
-
- // Here, we can handle a key event before the content gets it. When we are
- // fullscreen and it is not forced, we want to allow the user to leave
- // when ESC is pressed.
- // However, if the application has the "overrideEscFullscreen" permission, we
- // should let it override that behavior.
- // ::HandleKeyboardEvent() will only be called if the KeyEvent's default
- // action is not prevented.
- // Thus, we should handle the KeyEvent here only if the permission is not set.
- if (event.windowsKeyCode == ui::VKEY_ESCAPE && IsFullscreen() &&
- !IsForcedFullscreen() &&
- !extension->permissions_data()->HasAPIPermission(
- APIPermission::kOverrideEscFullscreen)) {
- Restore();
- return true;
- }
-
- return false;
-}
-
-void AppWindow::HandleKeyboardEvent(
- WebContents* source,
- const content::NativeWebKeyboardEvent& event) {
- // If the window is currently fullscreen and not forced, ESC should leave
- // fullscreen. If this code is being called for ESC, that means that the
- // KeyEvent's default behavior was not prevented by the content.
- if (event.windowsKeyCode == ui::VKEY_ESCAPE && IsFullscreen() &&
- !IsForcedFullscreen()) {
- Restore();
- return;
- }
-
- native_app_window_->HandleKeyboardEvent(event);
-}
-
-void AppWindow::RequestToLockMouse(WebContents* web_contents,
- bool user_gesture,
- bool last_unlocked_by_target) {
- DCHECK_EQ(AppWindow::web_contents(), web_contents);
- helper_->RequestToLockMouse();
-}
-
-bool AppWindow::PreHandleGestureEvent(WebContents* source,
- const blink::WebGestureEvent& event) {
- return extensions::AppWebContentsHelper::ShouldSuppressGestureEvent(event);
-}
-
-void AppWindow::DidFirstVisuallyNonEmptyPaint() {
- first_paint_complete_ = true;
- if (show_on_first_paint_) {
- DCHECK(delayed_show_type_ == SHOW_ACTIVE ||
- delayed_show_type_ == SHOW_INACTIVE);
- Show(delayed_show_type_);
- }
-}
-
-void AppWindow::OnNativeClose() {
- AppWindowRegistry::Get(browser_context_)->RemoveAppWindow(this);
- if (app_window_contents_) {
- WebContents* web_contents = app_window_contents_->GetWebContents();
- WebContentsModalDialogManager::FromWebContents(web_contents)
- ->SetDelegate(NULL);
- app_window_contents_->NativeWindowClosed();
- }
- delete this;
-}
-
-void AppWindow::OnNativeWindowChanged() {
- SaveWindowPosition();
-
-#if defined(OS_WIN)
- if (native_app_window_ && cached_always_on_top_ && !IsFullscreen() &&
- !native_app_window_->IsMaximized() &&
- !native_app_window_->IsMinimized()) {
- UpdateNativeAlwaysOnTop();
- }
-#endif
-
- if (app_window_contents_ && native_app_window_)
- app_window_contents_->NativeWindowChanged(native_app_window_.get());
-}
-
-void AppWindow::OnNativeWindowActivated() {
- AppWindowRegistry::Get(browser_context_)->AppWindowActivated(this);
-}
-
-content::WebContents* AppWindow::web_contents() const {
- return app_window_contents_->GetWebContents();
-}
-
-const extensions::Extension* AppWindow::GetExtension() const {
- return extensions::ExtensionRegistry::Get(browser_context_)
- ->enabled_extensions()
- .GetByID(extension_id_);
-}
-
-NativeAppWindow* AppWindow::GetBaseWindow() { return native_app_window_.get(); }
-
-gfx::NativeWindow AppWindow::GetNativeWindow() {
- return GetBaseWindow()->GetNativeWindow();
-}
-
-gfx::Rect AppWindow::GetClientBounds() const {
- gfx::Rect bounds = native_app_window_->GetBounds();
- bounds.Inset(native_app_window_->GetFrameInsets());
- return bounds;
-}
-
-base::string16 AppWindow::GetTitle() const {
- const extensions::Extension* extension = GetExtension();
- if (!extension)
- return base::string16();
-
- // WebContents::GetTitle() will return the page's URL if there's no <title>
- // specified. However, we'd prefer to show the name of the extension in that
- // case, so we directly inspect the NavigationEntry's title.
- base::string16 title;
- if (!web_contents() || !web_contents()->GetController().GetActiveEntry() ||
- web_contents()->GetController().GetActiveEntry()->GetTitle().empty()) {
- title = base::UTF8ToUTF16(extension->name());
- } else {
- title = web_contents()->GetTitle();
- }
- base::RemoveChars(title, base::ASCIIToUTF16("\n"), &title);
- return title;
-}
-
-void AppWindow::SetAppIconUrl(const GURL& url) {
- // If the same url is being used for the badge, ignore it.
- if (url == badge_icon_url_)
- return;
-
- // Avoid using any previous icons that were being downloaded.
- image_loader_ptr_factory_.InvalidateWeakPtrs();
-
- // Reset |app_icon_image_| to abort pending image load (if any).
- app_icon_image_.reset();
-
- app_icon_url_ = url;
- web_contents()->DownloadImage(
- url,
- true, // is a favicon
- 0, // no maximum size
- base::Bind(&AppWindow::DidDownloadFavicon,
- image_loader_ptr_factory_.GetWeakPtr()));
-}
-
-void AppWindow::SetBadgeIconUrl(const GURL& url) {
- // Avoid using any previous icons that were being downloaded.
- image_loader_ptr_factory_.InvalidateWeakPtrs();
-
- // Reset |app_icon_image_| to abort pending image load (if any).
- badge_icon_image_.reset();
-
- badge_icon_url_ = url;
- web_contents()->DownloadImage(
- url,
- true, // is a favicon
- 0, // no maximum size
- base::Bind(&AppWindow::DidDownloadFavicon,
- image_loader_ptr_factory_.GetWeakPtr()));
-}
-
-void AppWindow::ClearBadge() {
- badge_icon_image_.reset();
- badge_icon_url_ = GURL();
- UpdateBadgeIcon(gfx::Image());
-}
-
-void AppWindow::UpdateShape(scoped_ptr<SkRegion> region) {
- native_app_window_->UpdateShape(region.Pass());
-}
-
-void AppWindow::UpdateDraggableRegions(
- const std::vector<extensions::DraggableRegion>& regions) {
- native_app_window_->UpdateDraggableRegions(regions);
-}
-
-void AppWindow::UpdateAppIcon(const gfx::Image& image) {
- if (image.IsEmpty())
- return;
- app_icon_ = image;
- native_app_window_->UpdateWindowIcon();
- AppWindowRegistry::Get(browser_context_)->AppWindowIconChanged(this);
-}
-
-void AppWindow::SetFullscreen(FullscreenType type, bool enable) {
- DCHECK_NE(FULLSCREEN_TYPE_NONE, type);
-
- if (enable) {
-#if !defined(OS_MACOSX)
- // Do not enter fullscreen mode if disallowed by pref.
- // TODO(bartfab): Add a test once it becomes possible to simulate a user
- // gesture. http://crbug.com/174178
- if (type != FULLSCREEN_TYPE_FORCED) {
- PrefService* prefs =
- extensions::ExtensionsBrowserClient::Get()->GetPrefServiceForContext(
- browser_context());
- if (!prefs->GetBoolean(extensions::pref_names::kAppFullscreenAllowed))
- return;
- }
-#endif
- fullscreen_types_ |= type;
- } else {
- fullscreen_types_ &= ~type;
- }
- SetNativeWindowFullscreen();
-}
-
-bool AppWindow::IsFullscreen() const {
- return fullscreen_types_ != FULLSCREEN_TYPE_NONE;
-}
-
-bool AppWindow::IsForcedFullscreen() const {
- return (fullscreen_types_ & FULLSCREEN_TYPE_FORCED) != 0;
-}
-
-bool AppWindow::IsHtmlApiFullscreen() const {
- return (fullscreen_types_ & FULLSCREEN_TYPE_HTML_API) != 0;
-}
-
-void AppWindow::Fullscreen() {
- SetFullscreen(FULLSCREEN_TYPE_WINDOW_API, true);
-}
-
-void AppWindow::Maximize() { GetBaseWindow()->Maximize(); }
-
-void AppWindow::Minimize() { GetBaseWindow()->Minimize(); }
-
-void AppWindow::Restore() {
- if (IsFullscreen()) {
- fullscreen_types_ = FULLSCREEN_TYPE_NONE;
- SetNativeWindowFullscreen();
- } else {
- GetBaseWindow()->Restore();
- }
-}
-
-void AppWindow::OSFullscreen() {
- SetFullscreen(FULLSCREEN_TYPE_OS, true);
-}
-
-void AppWindow::ForcedFullscreen() {
- SetFullscreen(FULLSCREEN_TYPE_FORCED, true);
-}
-
-void AppWindow::SetContentSizeConstraints(const gfx::Size& min_size,
- const gfx::Size& max_size) {
- extensions::SizeConstraints constraints(min_size, max_size);
- native_app_window_->SetContentSizeConstraints(constraints.GetMinimumSize(),
- constraints.GetMaximumSize());
-
- gfx::Rect bounds = GetClientBounds();
- gfx::Size constrained_size = constraints.ClampSize(bounds.size());
- if (bounds.size() != constrained_size) {
- bounds.set_size(constrained_size);
- bounds.Inset(-native_app_window_->GetFrameInsets());
- native_app_window_->SetBounds(bounds);
- }
- OnNativeWindowChanged();
-}
-
-void AppWindow::Show(ShowType show_type) {
- is_hidden_ = false;
-
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- extensions::switches::kEnableAppsShowOnFirstPaint)) {
- show_on_first_paint_ = true;
-
- if (!first_paint_complete_) {
- delayed_show_type_ = show_type;
- return;
- }
- }
-
- switch (show_type) {
- case SHOW_ACTIVE:
- GetBaseWindow()->Show();
- break;
- case SHOW_INACTIVE:
- GetBaseWindow()->ShowInactive();
- break;
- }
- AppWindowRegistry::Get(browser_context_)->AppWindowShown(this);
-
- has_been_shown_ = true;
- SendOnWindowShownIfShown();
-}
-
-void AppWindow::Hide() {
- // This is there to prevent race conditions with Hide() being called before
- // there was a non-empty paint. It should have no effect in a non-racy
- // scenario where the application is hiding then showing a window: the second
- // show will not be delayed.
- is_hidden_ = true;
- show_on_first_paint_ = false;
- GetBaseWindow()->Hide();
- AppWindowRegistry::Get(browser_context_)->AppWindowHidden(this);
-}
-
-void AppWindow::SetAlwaysOnTop(bool always_on_top) {
- if (cached_always_on_top_ == always_on_top)
- return;
-
- cached_always_on_top_ = always_on_top;
-
- // As a security measure, do not allow fullscreen windows or windows that
- // overlap the taskbar to be on top. The property will be applied when the
- // window exits fullscreen and moves away from the taskbar.
- if (!IsFullscreen() && !IntersectsWithTaskbar())
- native_app_window_->SetAlwaysOnTop(always_on_top);
-
- OnNativeWindowChanged();
-}
-
-bool AppWindow::IsAlwaysOnTop() const { return cached_always_on_top_; }
-
-void AppWindow::WindowEventsReady() {
- can_send_events_ = true;
- SendOnWindowShownIfShown();
-}
-
-void AppWindow::GetSerializedState(base::DictionaryValue* properties) const {
- DCHECK(properties);
-
- properties->SetBoolean("fullscreen",
- native_app_window_->IsFullscreenOrPending());
- properties->SetBoolean("minimized", native_app_window_->IsMinimized());
- properties->SetBoolean("maximized", native_app_window_->IsMaximized());
- properties->SetBoolean("alwaysOnTop", IsAlwaysOnTop());
- properties->SetBoolean("hasFrameColor", native_app_window_->HasFrameColor());
- properties->SetBoolean(
- "alphaEnabled",
- requested_alpha_enabled_ && native_app_window_->CanHaveAlphaEnabled());
-
- // These properties are undocumented and are to enable testing. Alpha is
- // removed to
- // make the values easier to check.
- SkColor transparent_white = ~SK_ColorBLACK;
- properties->SetInteger(
- "activeFrameColor",
- native_app_window_->ActiveFrameColor() & transparent_white);
- properties->SetInteger(
- "inactiveFrameColor",
- native_app_window_->InactiveFrameColor() & transparent_white);
-
- gfx::Rect content_bounds = GetClientBounds();
- gfx::Size content_min_size = native_app_window_->GetContentMinimumSize();
- gfx::Size content_max_size = native_app_window_->GetContentMaximumSize();
- SetBoundsProperties(content_bounds,
- content_min_size,
- content_max_size,
- "innerBounds",
- properties);
-
- gfx::Insets frame_insets = native_app_window_->GetFrameInsets();
- gfx::Rect frame_bounds = native_app_window_->GetBounds();
- gfx::Size frame_min_size = extensions::SizeConstraints::AddFrameToConstraints(
- content_min_size, frame_insets);
- gfx::Size frame_max_size = extensions::SizeConstraints::AddFrameToConstraints(
- content_max_size, frame_insets);
- SetBoundsProperties(frame_bounds,
- frame_min_size,
- frame_max_size,
- "outerBounds",
- properties);
-}
-
-//------------------------------------------------------------------------------
-// Private methods
-
-void AppWindow::UpdateBadgeIcon(const gfx::Image& image) {
- badge_icon_ = image;
- native_app_window_->UpdateBadgeIcon();
-}
-
-void AppWindow::DidDownloadFavicon(
- int id,
- int http_status_code,
- const GURL& image_url,
- const std::vector<SkBitmap>& bitmaps,
- const std::vector<gfx::Size>& original_bitmap_sizes) {
- if ((image_url != app_icon_url_ && image_url != badge_icon_url_) ||
- bitmaps.empty()) {
- return;
- }
-
- // Bitmaps are ordered largest to smallest. Choose the smallest bitmap
- // whose height >= the preferred size.
- int largest_index = 0;
- for (size_t i = 1; i < bitmaps.size(); ++i) {
- if (bitmaps[i].height() < app_delegate_->PreferredIconSize())
- break;
- largest_index = i;
- }
- const SkBitmap& largest = bitmaps[largest_index];
- if (image_url == app_icon_url_) {
- UpdateAppIcon(gfx::Image::CreateFrom1xBitmap(largest));
- return;
- }
-
- UpdateBadgeIcon(gfx::Image::CreateFrom1xBitmap(largest));
-}
-
-void AppWindow::OnExtensionIconImageChanged(extensions::IconImage* image) {
- DCHECK_EQ(app_icon_image_.get(), image);
-
- UpdateAppIcon(gfx::Image(app_icon_image_->image_skia()));
-}
-
-void AppWindow::UpdateExtensionAppIcon() {
- // Avoid using any previous app icons were being downloaded.
- image_loader_ptr_factory_.InvalidateWeakPtrs();
-
- const extensions::Extension* extension = GetExtension();
- if (!extension)
- return;
-
- app_icon_image_.reset(
- new extensions::IconImage(browser_context(),
- extension,
- extensions::IconsInfo::GetIcons(extension),
- app_delegate_->PreferredIconSize(),
- app_delegate_->GetAppDefaultIcon(),
- this));
-
- // Triggers actual image loading with 1x resources. The 2x resource will
- // be handled by IconImage class when requested.
- app_icon_image_->image_skia().GetRepresentation(1.0f);
-}
-
-void AppWindow::SetNativeWindowFullscreen() {
- native_app_window_->SetFullscreen(fullscreen_types_);
-
- if (cached_always_on_top_)
- UpdateNativeAlwaysOnTop();
-}
-
-bool AppWindow::IntersectsWithTaskbar() const {
-#if defined(OS_WIN)
- gfx::Screen* screen = gfx::Screen::GetNativeScreen();
- gfx::Rect window_bounds = native_app_window_->GetRestoredBounds();
- std::vector<gfx::Display> displays = screen->GetAllDisplays();
-
- for (std::vector<gfx::Display>::const_iterator it = displays.begin();
- it != displays.end();
- ++it) {
- gfx::Rect taskbar_bounds = it->bounds();
- taskbar_bounds.Subtract(it->work_area());
- if (taskbar_bounds.IsEmpty())
- continue;
-
- if (window_bounds.Intersects(taskbar_bounds))
- return true;
- }
-#endif
-
- return false;
-}
-
-void AppWindow::UpdateNativeAlwaysOnTop() {
- DCHECK(cached_always_on_top_);
- bool is_on_top = native_app_window_->IsAlwaysOnTop();
- bool fullscreen = IsFullscreen();
- bool intersects_taskbar = IntersectsWithTaskbar();
-
- if (is_on_top && (fullscreen || intersects_taskbar)) {
- // When entering fullscreen or overlapping the taskbar, ensure windows are
- // not always-on-top.
- native_app_window_->SetAlwaysOnTop(false);
- } else if (!is_on_top && !fullscreen && !intersects_taskbar) {
- // When exiting fullscreen and moving away from the taskbar, reinstate
- // always-on-top.
- native_app_window_->SetAlwaysOnTop(true);
- }
-}
-
-void AppWindow::SendOnWindowShownIfShown() {
- if (!can_send_events_ || !has_been_shown_)
- return;
-
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType)) {
- app_window_contents_->DispatchWindowShownForTests();
- }
-}
-
-void AppWindow::CloseContents(WebContents* contents) {
- native_app_window_->Close();
-}
-
-bool AppWindow::ShouldSuppressDialogs() { return true; }
-
-content::ColorChooser* AppWindow::OpenColorChooser(
- WebContents* web_contents,
- SkColor initial_color,
- const std::vector<content::ColorSuggestion>& suggestions) {
- return app_delegate_->ShowColorChooser(web_contents, initial_color);
-}
-
-void AppWindow::RunFileChooser(WebContents* tab,
- const content::FileChooserParams& params) {
- if (window_type_is_panel()) {
- // Panels can't host a file dialog, abort. TODO(stevenjb): allow file
- // dialogs to be unhosted but still close with the owning web contents.
- // crbug.com/172502.
- LOG(WARNING) << "File dialog opened by panel.";
- return;
- }
-
- app_delegate_->RunFileChooser(tab, params);
-}
-
-bool AppWindow::IsPopupOrPanel(const WebContents* source) const { return true; }
-
-void AppWindow::MoveContents(WebContents* source, const gfx::Rect& pos) {
- native_app_window_->SetBounds(pos);
-}
-
-void AppWindow::NavigationStateChanged(const content::WebContents* source,
- content::InvalidateTypes changed_flags) {
- if (changed_flags & content::INVALIDATE_TYPE_TITLE)
- native_app_window_->UpdateWindowTitle();
- else if (changed_flags & content::INVALIDATE_TYPE_TAB)
- native_app_window_->UpdateWindowIcon();
-}
-
-void AppWindow::ToggleFullscreenModeForTab(content::WebContents* source,
- bool enter_fullscreen) {
- const extensions::Extension* extension = GetExtension();
- if (!extension)
- return;
-
- if (!IsExtensionWithPermissionOrSuggestInConsole(
- APIPermission::kFullscreen, extension, source->GetRenderViewHost())) {
- return;
- }
-
- SetFullscreen(FULLSCREEN_TYPE_HTML_API, enter_fullscreen);
-}
-
-bool AppWindow::IsFullscreenForTabOrPending(const content::WebContents* source)
- const {
- return IsHtmlApiFullscreen();
-}
-
-void AppWindow::Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- switch (type) {
- case extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: {
- const extensions::Extension* unloaded_extension =
- content::Details<extensions::UnloadedExtensionInfo>(details)
- ->extension;
- if (extension_id_ == unloaded_extension->id())
- native_app_window_->Close();
- break;
- }
- case extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED: {
- const extensions::Extension* installed_extension =
- content::Details<const extensions::InstalledExtensionInfo>(details)
- ->extension;
- DCHECK(installed_extension);
- if (installed_extension->id() == extension_id())
- native_app_window_->UpdateShelfMenu();
- break;
- }
- default:
- NOTREACHED() << "Received unexpected notification";
- }
-}
-
-void AppWindow::SetWebContentsBlocked(content::WebContents* web_contents,
- bool blocked) {
- app_delegate_->SetWebContentsBlocked(web_contents, blocked);
-}
-
-bool AppWindow::IsWebContentsVisible(content::WebContents* web_contents) {
- return app_delegate_->IsWebContentsVisible(web_contents);
-}
-
-WebContentsModalDialogHost* AppWindow::GetWebContentsModalDialogHost() {
- return native_app_window_.get();
-}
-
-void AppWindow::SaveWindowPosition() {
- if (window_key_.empty())
- return;
- if (!native_app_window_)
- return;
-
- extensions::AppWindowGeometryCache* cache =
- extensions::AppWindowGeometryCache::Get(browser_context());
-
- gfx::Rect bounds = native_app_window_->GetRestoredBounds();
- gfx::Rect screen_bounds =
- gfx::Screen::GetNativeScreen()->GetDisplayMatching(bounds).work_area();
- ui::WindowShowState window_state = native_app_window_->GetRestoredState();
- cache->SaveGeometry(
- extension_id(), window_key_, bounds, screen_bounds, window_state);
-}
-
-void AppWindow::AdjustBoundsToBeVisibleOnScreen(
- const gfx::Rect& cached_bounds,
- const gfx::Rect& cached_screen_bounds,
- const gfx::Rect& current_screen_bounds,
- const gfx::Size& minimum_size,
- gfx::Rect* bounds) const {
- *bounds = cached_bounds;
-
- // Reposition and resize the bounds if the cached_screen_bounds is different
- // from the current screen bounds and the current screen bounds doesn't
- // completely contain the bounds.
- if (cached_screen_bounds != current_screen_bounds &&
- !current_screen_bounds.Contains(cached_bounds)) {
- bounds->set_width(
- std::max(minimum_size.width(),
- std::min(bounds->width(), current_screen_bounds.width())));
- bounds->set_height(
- std::max(minimum_size.height(),
- std::min(bounds->height(), current_screen_bounds.height())));
- bounds->set_x(
- std::max(current_screen_bounds.x(),
- std::min(bounds->x(),
- current_screen_bounds.right() - bounds->width())));
- bounds->set_y(
- std::max(current_screen_bounds.y(),
- std::min(bounds->y(),
- current_screen_bounds.bottom() - bounds->height())));
- }
-}
-
-AppWindow::CreateParams AppWindow::LoadDefaults(CreateParams params)
- const {
- // Ensure width and height are specified.
- if (params.content_spec.bounds.width() == 0 &&
- params.window_spec.bounds.width() == 0) {
- params.content_spec.bounds.set_width(kDefaultWidth);
- }
- if (params.content_spec.bounds.height() == 0 &&
- params.window_spec.bounds.height() == 0) {
- params.content_spec.bounds.set_height(kDefaultHeight);
- }
-
- // If left and top are left undefined, the native app window will center
- // the window on the main screen in a platform-defined manner.
-
- // Load cached state if it exists.
- if (!params.window_key.empty()) {
- extensions::AppWindowGeometryCache* cache =
- extensions::AppWindowGeometryCache::Get(browser_context());
-
- gfx::Rect cached_bounds;
- gfx::Rect cached_screen_bounds;
- ui::WindowShowState cached_state = ui::SHOW_STATE_DEFAULT;
- if (cache->GetGeometry(extension_id(),
- params.window_key,
- &cached_bounds,
- &cached_screen_bounds,
- &cached_state)) {
- // App window has cached screen bounds, make sure it fits on screen in
- // case the screen resolution changed.
- gfx::Screen* screen = gfx::Screen::GetNativeScreen();
- gfx::Display display = screen->GetDisplayMatching(cached_bounds);
- gfx::Rect current_screen_bounds = display.work_area();
- extensions::SizeConstraints constraints(
- params.GetWindowMinimumSize(gfx::Insets()),
- params.GetWindowMaximumSize(gfx::Insets()));
- AdjustBoundsToBeVisibleOnScreen(cached_bounds,
- cached_screen_bounds,
- current_screen_bounds,
- constraints.GetMinimumSize(),
- &params.window_spec.bounds);
- params.state = cached_state;
-
- // Since we are restoring a cached state, reset the content bounds spec to
- // ensure it is not used.
- params.content_spec.ResetBounds();
- }
- }
-
- return params;
-}
-
-// static
-SkRegion* AppWindow::RawDraggableRegionsToSkRegion(
- const std::vector<extensions::DraggableRegion>& regions) {
- SkRegion* sk_region = new SkRegion;
- for (std::vector<extensions::DraggableRegion>::const_iterator iter =
- regions.begin();
- iter != regions.end();
- ++iter) {
- const extensions::DraggableRegion& region = *iter;
- sk_region->op(
- region.bounds.x(),
- region.bounds.y(),
- region.bounds.right(),
- region.bounds.bottom(),
- region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op);
- }
- return sk_region;
-}
-
-} // namespace apps
« no previous file with comments | « apps/app_window.h ('k') | apps/app_window_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698