15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/app_window/app_window.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <algorithm>
8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <string>
9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <vector>
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/command_line.h"
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/string_util.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "components/web_modal/web_contents_modal_dialog_manager.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/browser_context.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/invalidate_type.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_entry.h"
1934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#include "content/public/browser/notification_details.h"
2034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#include "content/public/browser/notification_service.h"
2134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#include "content/public/browser/notification_source.h"
2234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#include "content/public/browser/notification_types.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/resource_dispatcher_host.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "content/public/common/content_switches.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/media_stream_request.h"
2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/browser/app_window/app_delegate.h"
2903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/browser/app_window/app_web_contents_helper.h"
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/app_window/app_window_client.h"
3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/browser/app_window/app_window_geometry_cache.h"
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/app_window/app_window_registry.h"
3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/browser/app_window/native_app_window.h"
3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/browser/app_window/size_constraints.h"
35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "extensions/browser/extension_registry.h"
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extensions_browser_client.h"
3834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)#include "extensions/browser/notification_types.h"
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/process_manager.h"
4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/browser/suggest_permission_util.h"
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "extensions/browser/view_type_utils.h"
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/common/draggable_region.h"
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/manifest_handlers/icons_handler.h"
4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/permissions/permissions_data.h"
4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/common/switches.h"
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/grit/extensions_browser_resources.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkRegion.h"
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/base/resource/resource_bundle.h"
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/screen.h"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#if !defined(OS_MACOSX)
53424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/prefs/pref_service.h"
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/pref_names.h"
55424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#endif
56424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using content::BrowserContext;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::ConsoleMessageLevel;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using web_modal::WebContentsModalDialogHost;
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using web_modal::WebContentsModalDialogManager;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace extensions {
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDefaultWidth = 512;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDefaultHeight = 384;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void SetConstraintProperty(const std::string& name,
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           int value,
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           base::DictionaryValue* bounds_properties) {
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (value != SizeConstraints::kUnboundedSize)
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bounds_properties->SetInteger(name, value);
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  else
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bounds_properties->Set(name, base::Value::CreateNullValue());
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void SetBoundsProperties(const gfx::Rect& bounds,
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         const gfx::Size& min_size,
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         const gfx::Size& max_size,
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         const std::string& bounds_name,
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         base::DictionaryValue* window_properties) {
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> bounds_properties(
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      new base::DictionaryValue());
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bounds_properties->SetInteger("left", bounds.x());
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bounds_properties->SetInteger("top", bounds.y());
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bounds_properties->SetInteger("width", bounds.width());
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bounds_properties->SetInteger("height", bounds.height());
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetConstraintProperty("minWidth", min_size.width(), bounds_properties.get());
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetConstraintProperty(
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      "minHeight", min_size.height(), bounds_properties.get());
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetConstraintProperty("maxWidth", max_size.width(), bounds_properties.get());
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetConstraintProperty(
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      "maxHeight", max_size.height(), bounds_properties.get());
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window_properties->Set(bounds_name, bounds_properties.release());
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Combines the constraints of the content and window, and returns constraints
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// for the window.
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)gfx::Size GetCombinedWindowConstraints(const gfx::Size& window_constraints,
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                       const gfx::Size& content_constraints,
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                       const gfx::Insets& frame_insets) {
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Size combined_constraints(window_constraints);
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (content_constraints.width() > 0) {
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    combined_constraints.set_width(
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        content_constraints.width() + frame_insets.width());
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (content_constraints.height() > 0) {
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    combined_constraints.set_height(
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        content_constraints.height() + frame_insets.height());
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return combined_constraints;
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Combines the constraints of the content and window, and returns constraints
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// for the content.
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)gfx::Size GetCombinedContentConstraints(const gfx::Size& window_constraints,
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                        const gfx::Size& content_constraints,
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                        const gfx::Insets& frame_insets) {
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Size combined_constraints(content_constraints);
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (window_constraints.width() > 0) {
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    combined_constraints.set_width(
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        std::max(0, window_constraints.width() - frame_insets.width()));
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (window_constraints.height() > 0) {
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    combined_constraints.set_height(
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        std::max(0, window_constraints.height() - frame_insets.height()));
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return combined_constraints;
1348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace
1378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// AppWindow::BoundsSpecification
1398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const int AppWindow::BoundsSpecification::kUnspecifiedPosition = INT_MIN;
1418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AppWindow::BoundsSpecification::BoundsSpecification()
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : bounds(kUnspecifiedPosition, kUnspecifiedPosition, 0, 0) {}
1448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AppWindow::BoundsSpecification::~BoundsSpecification() {}
1468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AppWindow::BoundsSpecification::ResetBounds() {
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bounds.SetRect(kUnspecifiedPosition, kUnspecifiedPosition, 0, 0);
1498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// AppWindow::CreateParams
1528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppWindow::CreateParams::CreateParams()
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : window_type(AppWindow::WINDOW_TYPE_DEFAULT),
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      frame(AppWindow::FRAME_CHROME),
156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      has_frame_color(false),
157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      active_frame_color(SK_ColorBLACK),
158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      inactive_frame_color(SK_ColorBLACK),
1596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      alpha_enabled(false),
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      creator_process_id(0),
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      state(ui::SHOW_STATE_DEFAULT),
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      hidden(false),
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      resizable(true),
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      focused(true),
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      always_on_top(false),
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      visible_on_all_workspaces(false) {
1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppWindow::CreateParams::~CreateParams() {}
170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)gfx::Rect AppWindow::CreateParams::GetInitialWindowBounds(
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const gfx::Insets& frame_insets) const {
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Combine into a single window bounds.
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Rect combined_bounds(window_spec.bounds);
175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (content_spec.bounds.x() != BoundsSpecification::kUnspecifiedPosition)
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    combined_bounds.set_x(content_spec.bounds.x() - frame_insets.left());
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (content_spec.bounds.y() != BoundsSpecification::kUnspecifiedPosition)
178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    combined_bounds.set_y(content_spec.bounds.y() - frame_insets.top());
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (content_spec.bounds.width() > 0) {
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    combined_bounds.set_width(
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        content_spec.bounds.width() + frame_insets.width());
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (content_spec.bounds.height() > 0) {
184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    combined_bounds.set_height(
185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        content_spec.bounds.height() + frame_insets.height());
186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Constrain the bounds.
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SizeConstraints constraints(
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      GetCombinedWindowConstraints(
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          window_spec.minimum_size, content_spec.minimum_size, frame_insets),
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      GetCombinedWindowConstraints(
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          window_spec.maximum_size, content_spec.maximum_size, frame_insets));
194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  combined_bounds.set_size(constraints.ClampSize(combined_bounds.size()));
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return combined_bounds;
197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)gfx::Size AppWindow::CreateParams::GetContentMinimumSize(
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const gfx::Insets& frame_insets) const {
201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return GetCombinedContentConstraints(window_spec.minimum_size,
202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                       content_spec.minimum_size,
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                       frame_insets);
204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)gfx::Size AppWindow::CreateParams::GetContentMaximumSize(
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const gfx::Insets& frame_insets) const {
208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return GetCombinedContentConstraints(window_spec.maximum_size,
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                       content_spec.maximum_size,
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                       frame_insets);
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)gfx::Size AppWindow::CreateParams::GetWindowMinimumSize(
214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const gfx::Insets& frame_insets) const {
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return GetCombinedWindowConstraints(window_spec.minimum_size,
216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                      content_spec.minimum_size,
217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                      frame_insets);
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)gfx::Size AppWindow::CreateParams::GetWindowMaximumSize(
221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const gfx::Insets& frame_insets) const {
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return GetCombinedWindowConstraints(window_spec.maximum_size,
223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                      content_spec.maximum_size,
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                      frame_insets);
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// AppWindow
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppWindow::AppWindow(BrowserContext* context,
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     AppDelegate* app_delegate,
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     const Extension* extension)
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : browser_context_(context),
23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      extension_id_(extension->id()),
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      window_type_(WINDOW_TYPE_DEFAULT),
2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      app_delegate_(app_delegate),
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      image_loader_ptr_factory_(this),
237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      fullscreen_types_(FULLSCREEN_TYPE_NONE),
238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      show_on_first_paint_(false),
239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      first_paint_complete_(false),
24046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      has_been_shown_(false),
24146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      can_send_events_(false),
242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      is_hidden_(false),
243116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      cached_always_on_top_(false),
2446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      requested_alpha_enabled_(false) {
2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ExtensionsBrowserClient* client = ExtensionsBrowserClient::Get();
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK(!client->IsGuestSession(context) || context->IsOffTheRecord())
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      << "Only off the record window may be opened in the guest mode.";
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::Init(const GURL& url,
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     AppWindowContents* app_window_contents,
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     const CreateParams& params) {
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Initialize the render interface and web contents
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  app_window_contents_.reset(app_window_contents);
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  app_window_contents_->Initialize(browser_context(), url);
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WebContents* web_contents = app_window_contents_->GetWebContents();
257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch(
2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          switches::kEnableAppsShowOnFirstPaint)) {
259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    content::WebContentsObserver::Observe(web_contents);
260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  app_delegate_->InitWebContents(web_contents);
262116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WebContentsModalDialogManager::CreateForWebContents(web_contents);
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  web_contents->SetDelegate(this);
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WebContentsModalDialogManager::FromWebContents(web_contents)
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ->SetDelegate(this);
2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SetViewType(web_contents, VIEW_TYPE_APP_WINDOW);
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Initialize the window
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CreateParams new_params = LoadDefaults(params);
2728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  window_type_ = new_params.window_type;
2738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  window_key_ = new_params.window_key;
274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Windows cannot be always-on-top in fullscreen mode for security reasons.
276f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  cached_always_on_top_ = new_params.always_on_top;
277f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (new_params.state == ui::SHOW_STATE_FULLSCREEN)
278f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    new_params.always_on_top = false;
279f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  requested_alpha_enabled_ = new_params.alpha_enabled;
281116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  AppWindowClient* app_window_client = AppWindowClient::Get();
2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  native_app_window_.reset(
2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      app_window_client->CreateNativeAppWindow(this, new_params));
2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  helper_.reset(new AppWebContentsHelper(
2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      browser_context_, extension_id_, web_contents, app_delegate_.get()));
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
289116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  popup_manager_.reset(
290116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      new web_modal::PopupManager(GetWebContentsModalDialogHost()));
291116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  popup_manager_->RegisterWith(web_contents);
292116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UpdateExtensionAppIcon();
294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  AppWindowRegistry::Get(browser_context_)->AddAppWindow(this);
295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
296010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (new_params.hidden) {
297010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Although the window starts hidden by default, calling Hide() here
298010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // notifies observers of the window being hidden.
299010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    Hide();
300010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else {
301f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Panels are not activated by default.
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Show(window_type_is_panel() || !new_params.focused ? SHOW_INACTIVE
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                       : SHOW_ACTIVE);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
306b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (new_params.state == ui::SHOW_STATE_FULLSCREEN)
307b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    Fullscreen();
308b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  else if (new_params.state == ui::SHOW_STATE_MAXIMIZED)
309b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    Maximize();
310b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  else if (new_params.state == ui::SHOW_STATE_MINIMIZED)
311b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    Minimize();
312b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
313b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  OnNativeWindowChanged();
314b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
31534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  // When the render view host is changed, the native window needs to know
31634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  // about it in case it has any setup to do to make the renderer appear
31734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  // properly. In particular, on Windows, the view's clickthrough region needs
31834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  // to be set.
31934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  ExtensionsBrowserClient* client = ExtensionsBrowserClient::Get();
32034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  registrar_.Add(this,
32134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)                 NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
32234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)                 content::Source<content::BrowserContext>(
32334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)                     client->GetOriginalContext(browser_context_)));
32434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  // Update the app menu if an ephemeral app becomes installed.
32534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  registrar_.Add(
32634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)      this,
32734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)      NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
32834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)      content::Source<content::BrowserContext>(
32934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)          client->GetOriginalContext(browser_context_)));
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Close when the browser process is exiting.
33203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  app_delegate_->SetTerminatingCallback(
33303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      base::Bind(&NativeAppWindow::Close,
33403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                 base::Unretained(native_app_window_.get())));
33503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  app_window_contents_->LoadContents(new_params.creator_process_id);
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
338f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch(
33903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          extensions::switches::kEnableAppsShowOnFirstPaint)) {
340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // We want to show the window only when the content has been painted. For
341f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // that to happen, we need to define a size for the content, otherwise the
342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // layout will happen in a 0x0 area.
343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    gfx::Insets frame_insets = native_app_window_->GetFrameInsets();
344a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    gfx::Rect initial_bounds = new_params.GetInitialWindowBounds(frame_insets);
345a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    initial_bounds.Inset(frame_insets);
3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    app_delegate_->ResizeWebContents(web_contents, initial_bounds.size());
347f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppWindow::~AppWindow() {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::RequestMediaAccessPermission(
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::WebContents* web_contents,
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::MediaStreamRequest& request,
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::MediaResponseCallback& callback) {
3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_EQ(AppWindow::web_contents(), web_contents);
3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  helper_->RequestMediaAccessPermission(request, callback);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool AppWindow::CheckMediaAccessPermission(content::WebContents* web_contents,
3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                           const GURL& security_origin,
3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                           content::MediaStreamType type) {
3641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_EQ(AppWindow::web_contents(), web_contents);
3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return helper_->CheckMediaAccessPermission(security_origin, type);
3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WebContents* AppWindow::OpenURLFromTab(WebContents* source,
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       const content::OpenURLParams& params) {
3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_EQ(web_contents(), source);
3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return helper_->OpenURLFromTab(params);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::AddNewContents(WebContents* source,
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               WebContents* new_contents,
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               WindowOpenDisposition disposition,
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               const gfx::Rect& initial_pos,
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               bool user_gesture,
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               bool* was_blocked) {
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(new_contents->GetBrowserContext() == browser_context_);
3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  app_delegate_->AddNewContents(browser_context_,
3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                new_contents,
3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                disposition,
3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                initial_pos,
3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                user_gesture,
3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                was_blocked);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool AppWindow::PreHandleKeyboardEvent(
390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    content::WebContents* source,
391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const content::NativeWebKeyboardEvent& event,
392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool* is_keyboard_shortcut) {
3931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const Extension* extension = GetExtension();
394010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!extension)
395010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return false;
396010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
397f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Here, we can handle a key event before the content gets it. When we are
3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // fullscreen and it is not forced, we want to allow the user to leave
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // when ESC is pressed.
400f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // However, if the application has the "overrideEscFullscreen" permission, we
401f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // should let it override that behavior.
402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // ::HandleKeyboardEvent() will only be called if the KeyEvent's default
403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // action is not prevented.
404f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Thus, we should handle the KeyEvent here only if the permission is not set.
4055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (event.windowsKeyCode == ui::VKEY_ESCAPE && IsFullscreen() &&
4065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      !IsForcedFullscreen() &&
40746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      !extension->permissions_data()->HasAPIPermission(
40846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          APIPermission::kOverrideEscFullscreen)) {
409f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Restore();
410f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return true;
411f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
412f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
413f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return false;
414f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
415f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::HandleKeyboardEvent(
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebContents* source,
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NativeWebKeyboardEvent& event) {
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If the window is currently fullscreen and not forced, ESC should leave
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // fullscreen.  If this code is being called for ESC, that means that the
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // KeyEvent's default behavior was not prevented by the content.
4225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (event.windowsKeyCode == ui::VKEY_ESCAPE && IsFullscreen() &&
4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      !IsForcedFullscreen()) {
424f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Restore();
425f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
426f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
427f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  native_app_window_->HandleKeyboardEvent(event);
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::RequestToLockMouse(WebContents* web_contents,
4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   bool user_gesture,
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   bool last_unlocked_by_target) {
4345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_EQ(AppWindow::web_contents(), web_contents);
4355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  helper_->RequestToLockMouse();
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool AppWindow::PreHandleGestureEvent(WebContents* source,
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      const blink::WebGestureEvent& event) {
4401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return AppWebContentsHelper::ShouldSuppressGestureEvent(event);
4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
443010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void AppWindow::DidFirstVisuallyNonEmptyPaint() {
444f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  first_paint_complete_ = true;
445f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (show_on_first_paint_) {
446f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(delayed_show_type_ == SHOW_ACTIVE ||
447f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           delayed_show_type_ == SHOW_INACTIVE);
448f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Show(delayed_show_type_);
449f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
450f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
451f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::OnNativeClose() {
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppWindowRegistry::Get(browser_context_)->RemoveAppWindow(this);
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (app_window_contents_) {
4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WebContents* web_contents = app_window_contents_->GetWebContents();
4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WebContentsModalDialogManager::FromWebContents(web_contents)
4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ->SetDelegate(NULL);
4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    app_window_contents_->NativeWindowClosed();
4594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete this;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::OnNativeWindowChanged() {
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SaveWindowPosition();
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN)
4675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (native_app_window_ && cached_always_on_top_ && !IsFullscreen() &&
4685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      !native_app_window_->IsMaximized() &&
4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !native_app_window_->IsMinimized()) {
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UpdateNativeAlwaysOnTop();
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (app_window_contents_ && native_app_window_)
4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    app_window_contents_->NativeWindowChanged(native_app_window_.get());
47690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
47790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::OnNativeWindowActivated() {
4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppWindowRegistry::Get(browser_context_)->AppWindowActivated(this);
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)content::WebContents* AppWindow::web_contents() const {
4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return app_window_contents_->GetWebContents();
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst Extension* AppWindow::GetExtension() const {
4871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return ExtensionRegistry::Get(browser_context_)
488010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ->enabled_extensions()
489010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      .GetByID(extension_id_);
490010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
491010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NativeAppWindow* AppWindow::GetBaseWindow() { return native_app_window_.get(); }
4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)gfx::NativeWindow AppWindow::GetNativeWindow() {
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return GetBaseWindow()->GetNativeWindow();
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)gfx::Rect AppWindow::GetClientBounds() const {
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect bounds = native_app_window_->GetBounds();
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bounds.Inset(native_app_window_->GetFrameInsets());
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return bounds;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 AppWindow::GetTitle() const {
5051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const Extension* extension = GetExtension();
506010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!extension)
507cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return base::string16();
508010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WebContents::GetTitle() will return the page's URL if there's no <title>
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // specified. However, we'd prefer to show the name of the extension in that
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // case, so we directly inspect the NavigationEntry's title.
512cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::string16 title;
5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!web_contents() || !web_contents()->GetController().GetActiveEntry() ||
514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      web_contents()->GetController().GetActiveEntry()->GetTitle().empty()) {
515010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    title = base::UTF8ToUTF16(extension->name());
516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } else {
517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    title = web_contents()->GetTitle();
518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
519cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::RemoveChars(title, base::ASCIIToUTF16("\n"), &title);
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return title;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::SetAppIconUrl(const GURL& url) {
5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If the same url is being used for the badge, ignore it.
5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (url == badge_icon_url_)
5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Avoid using any previous icons that were being downloaded.
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  image_loader_ptr_factory_.InvalidateWeakPtrs();
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
531a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Reset |app_icon_image_| to abort pending image load (if any).
532a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  app_icon_image_.reset();
533a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  app_icon_url_ = url;
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  web_contents()->DownloadImage(
536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      url,
537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      true,  // is a favicon
5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      0,     // no maximum size
5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&AppWindow::DidDownloadFavicon,
5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 image_loader_ptr_factory_.GetWeakPtr()));
5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::SetBadgeIconUrl(const GURL& url) {
5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Avoid using any previous icons that were being downloaded.
5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  image_loader_ptr_factory_.InvalidateWeakPtrs();
5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Reset |app_icon_image_| to abort pending image load (if any).
5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  badge_icon_image_.reset();
5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  badge_icon_url_ = url;
5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  web_contents()->DownloadImage(
5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      url,
5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      true,  // is a favicon
5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      0,     // no maximum size
5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&AppWindow::DidDownloadFavicon,
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 image_loader_ptr_factory_.GetWeakPtr()));
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::ClearBadge() {
5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  badge_icon_image_.reset();
5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  badge_icon_url_ = GURL();
5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UpdateBadgeIcon(gfx::Image());
5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::UpdateShape(scoped_ptr<SkRegion> region) {
566f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  native_app_window_->UpdateShape(region.Pass());
5673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::UpdateDraggableRegions(
5701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::vector<DraggableRegion>& regions) {
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  native_app_window_->UpdateDraggableRegions(regions);
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::UpdateAppIcon(const gfx::Image& image) {
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (image.IsEmpty())
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  app_icon_ = image;
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  native_app_window_->UpdateWindowIcon();
5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppWindowRegistry::Get(browser_context_)->AppWindowIconChanged(this);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void AppWindow::SetFullscreen(FullscreenType type, bool enable) {
5835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_NE(FULLSCREEN_TYPE_NONE, type);
5845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (enable) {
586d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if !defined(OS_MACOSX)
5875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Do not enter fullscreen mode if disallowed by pref.
5885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // TODO(bartfab): Add a test once it becomes possible to simulate a user
5895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // gesture. http://crbug.com/174178
5905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (type != FULLSCREEN_TYPE_FORCED) {
5915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      PrefService* prefs =
5921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          ExtensionsBrowserClient::Get()->GetPrefServiceForContext(
5935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              browser_context());
5941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (!prefs->GetBoolean(pref_names::kAppFullscreenAllowed))
5955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return;
5965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
597d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif
5985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    fullscreen_types_ |= type;
5995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else {
6005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    fullscreen_types_ &= ~type;
6015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetNativeWindowFullscreen();
603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool AppWindow::IsFullscreen() const {
6065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return fullscreen_types_ != FULLSCREEN_TYPE_NONE;
6075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
6085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool AppWindow::IsForcedFullscreen() const {
6105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return (fullscreen_types_ & FULLSCREEN_TYPE_FORCED) != 0;
6115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
6125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool AppWindow::IsHtmlApiFullscreen() const {
6145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return (fullscreen_types_ & FULLSCREEN_TYPE_HTML_API) != 0;
6155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
6165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void AppWindow::Fullscreen() {
6185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SetFullscreen(FULLSCREEN_TYPE_WINDOW_API, true);
6195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
6205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::Maximize() { GetBaseWindow()->Maximize(); }
622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::Minimize() { GetBaseWindow()->Minimize(); }
624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::Restore() {
6265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (IsFullscreen()) {
627f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    fullscreen_types_ = FULLSCREEN_TYPE_NONE;
6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SetNativeWindowFullscreen();
629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    GetBaseWindow()->Restore();
631c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::OSFullscreen() {
6355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SetFullscreen(FULLSCREEN_TYPE_OS, true);
6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
6375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::ForcedFullscreen() {
6395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SetFullscreen(FULLSCREEN_TYPE_FORCED, true);
640f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
641f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
642a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AppWindow::SetContentSizeConstraints(const gfx::Size& min_size,
643a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          const gfx::Size& max_size) {
6441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SizeConstraints constraints(min_size, max_size);
645a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  native_app_window_->SetContentSizeConstraints(constraints.GetMinimumSize(),
646a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                constraints.GetMaximumSize());
6478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
648a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Rect bounds = GetClientBounds();
649a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Size constrained_size = constraints.ClampSize(bounds.size());
650a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (bounds.size() != constrained_size) {
651a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bounds.set_size(constrained_size);
652a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bounds.Inset(-native_app_window_->GetFrameInsets());
653a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    native_app_window_->SetBounds(bounds);
654a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
655a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  OnNativeWindowChanged();
6568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
6578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::Show(ShowType show_type) {
659cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  is_hidden_ = false;
660cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
661f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch(
6621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          switches::kEnableAppsShowOnFirstPaint)) {
663f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    show_on_first_paint_ = true;
664f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
665f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!first_paint_complete_) {
666f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      delayed_show_type_ = show_type;
667f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return;
668f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
669f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
670f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
671f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  switch (show_type) {
672f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SHOW_ACTIVE:
673f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      GetBaseWindow()->Show();
674f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      break;
675f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SHOW_INACTIVE:
676f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      GetBaseWindow()->ShowInactive();
677f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      break;
678f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
679010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  AppWindowRegistry::Get(browser_context_)->AppWindowShown(this);
68046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
68146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  has_been_shown_ = true;
68246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SendOnWindowShownIfShown();
683f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
684f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
6855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::Hide() {
686f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // This is there to prevent race conditions with Hide() being called before
687f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // there was a non-empty paint. It should have no effect in a non-racy
688f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // scenario where the application is hiding then showing a window: the second
689f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // show will not be delayed.
690cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  is_hidden_ = true;
691f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  show_on_first_paint_ = false;
692f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  GetBaseWindow()->Hide();
693010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  AppWindowRegistry::Get(browser_context_)->AppWindowHidden(this);
694f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
695f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
6965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::SetAlwaysOnTop(bool always_on_top) {
697f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (cached_always_on_top_ == always_on_top)
698f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
699f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
700f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  cached_always_on_top_ = always_on_top;
701f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // As a security measure, do not allow fullscreen windows or windows that
7035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // overlap the taskbar to be on top. The property will be applied when the
7045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // window exits fullscreen and moves away from the taskbar.
7055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!IsFullscreen() && !IntersectsWithTaskbar())
706f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    native_app_window_->SetAlwaysOnTop(always_on_top);
707f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
708f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OnNativeWindowChanged();
709f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
710f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool AppWindow::IsAlwaysOnTop() const { return cached_always_on_top_; }
7125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
71346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppWindow::WindowEventsReady() {
71446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  can_send_events_ = true;
71546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SendOnWindowShownIfShown();
71646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
71746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
7185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::GetSerializedState(base::DictionaryValue* properties) const {
7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(properties);
7205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  properties->SetBoolean("fullscreen",
7225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         native_app_window_->IsFullscreenOrPending());
7235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  properties->SetBoolean("minimized", native_app_window_->IsMinimized());
7245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  properties->SetBoolean("maximized", native_app_window_->IsMaximized());
7255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  properties->SetBoolean("alwaysOnTop", IsAlwaysOnTop());
726a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  properties->SetBoolean("hasFrameColor", native_app_window_->HasFrameColor());
7276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  properties->SetBoolean(
7286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      "alphaEnabled",
7296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      requested_alpha_enabled_ && native_app_window_->CanHaveAlphaEnabled());
7305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
7315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // These properties are undocumented and are to enable testing. Alpha is
7325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // removed to
7335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // make the values easier to check.
7345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SkColor transparent_white = ~SK_ColorBLACK;
7355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  properties->SetInteger(
7365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      "activeFrameColor",
7375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      native_app_window_->ActiveFrameColor() & transparent_white);
7385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  properties->SetInteger(
7395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      "inactiveFrameColor",
7405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      native_app_window_->InactiveFrameColor() & transparent_white);
741a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
742a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Rect content_bounds = GetClientBounds();
743a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Size content_min_size = native_app_window_->GetContentMinimumSize();
744a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Size content_max_size = native_app_window_->GetContentMaximumSize();
745a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetBoundsProperties(content_bounds,
746a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      content_min_size,
747a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      content_max_size,
748a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      "innerBounds",
749a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      properties);
750a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
751a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Insets frame_insets = native_app_window_->GetFrameInsets();
752a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Rect frame_bounds = native_app_window_->GetBounds();
7531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Size frame_min_size = SizeConstraints::AddFrameToConstraints(
75403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      content_min_size, frame_insets);
7551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Size frame_max_size = SizeConstraints::AddFrameToConstraints(
75603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      content_max_size, frame_insets);
757a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetBoundsProperties(frame_bounds,
758a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      frame_min_size,
759a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      frame_max_size,
760a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      "outerBounds",
761a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      properties);
762f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
763f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//------------------------------------------------------------------------------
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Private methods
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::UpdateBadgeIcon(const gfx::Image& image) {
7685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  badge_icon_ = image;
7695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  native_app_window_->UpdateBadgeIcon();
7705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
7715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::DidDownloadFavicon(
773d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    int id,
774d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    int http_status_code,
775d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const GURL& image_url,
776d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const std::vector<SkBitmap>& bitmaps,
777d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const std::vector<gfx::Size>& original_bitmap_sizes) {
7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if ((image_url != app_icon_url_ && image_url != badge_icon_url_) ||
7795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bitmaps.empty()) {
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Bitmaps are ordered largest to smallest. Choose the smallest bitmap
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // whose height >= the preferred size.
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int largest_index = 0;
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 1; i < bitmaps.size(); ++i) {
7875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (bitmaps[i].height() < app_delegate_->PreferredIconSize())
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    largest_index = i;
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const SkBitmap& largest = bitmaps[largest_index];
7925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (image_url == app_icon_url_) {
7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UpdateAppIcon(gfx::Image::CreateFrom1xBitmap(largest));
7945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UpdateBadgeIcon(gfx::Image::CreateFrom1xBitmap(largest));
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AppWindow::OnExtensionIconImageChanged(IconImage* image) {
801a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK_EQ(app_icon_image_.get(), image);
802a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
803a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  UpdateAppIcon(gfx::Image(app_icon_image_->image_skia()));
804a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
805a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::UpdateExtensionAppIcon() {
8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Avoid using any previous app icons were being downloaded.
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  image_loader_ptr_factory_.InvalidateWeakPtrs();
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const Extension* extension = GetExtension();
811010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!extension)
812010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
813010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
8141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::ImageSkia app_default_icon =
8151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
8161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          IDR_APP_DEFAULT_ICON);
8171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  app_icon_image_.reset(new IconImage(browser_context(),
8191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                      extension,
8201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                      IconsInfo::GetIcons(extension),
8211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                      app_delegate_->PreferredIconSize(),
8221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                      app_default_icon,
8231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                      this));
824a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
825a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Triggers actual image loading with 1x resources. The 2x resource will
826a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // be handled by IconImage class when requested.
82768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  app_icon_image_->image_skia().GetRepresentation(1.0f);
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::SetNativeWindowFullscreen() {
8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  native_app_window_->SetFullscreen(fullscreen_types_);
832f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
8335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (cached_always_on_top_)
8345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UpdateNativeAlwaysOnTop();
8355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
8365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool AppWindow::IntersectsWithTaskbar() const {
8385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN)
8395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Screen* screen = gfx::Screen::GetNativeScreen();
8405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Rect window_bounds = native_app_window_->GetRestoredBounds();
8415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<gfx::Display> displays = screen->GetAllDisplays();
8425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (std::vector<gfx::Display>::const_iterator it = displays.begin();
8445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       it != displays.end();
8455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       ++it) {
8465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gfx::Rect taskbar_bounds = it->bounds();
8475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    taskbar_bounds.Subtract(it->work_area());
8485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (taskbar_bounds.IsEmpty())
8495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      continue;
8505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (window_bounds.Intersects(taskbar_bounds))
8525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return true;
8535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
8545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
8555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return false;
8575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
858f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
8595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::UpdateNativeAlwaysOnTop() {
8605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(cached_always_on_top_);
861f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool is_on_top = native_app_window_->IsAlwaysOnTop();
8625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool fullscreen = IsFullscreen();
8635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool intersects_taskbar = IntersectsWithTaskbar();
8645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (is_on_top && (fullscreen || intersects_taskbar)) {
8665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // When entering fullscreen or overlapping the taskbar, ensure windows are
8675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // not always-on-top.
868f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    native_app_window_->SetAlwaysOnTop(false);
8695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (!is_on_top && !fullscreen && !intersects_taskbar) {
8705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // When exiting fullscreen and moving away from the taskbar, reinstate
8715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // always-on-top.
872f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    native_app_window_->SetAlwaysOnTop(true);
873f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
874f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
875f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
87646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AppWindow::SendOnWindowShownIfShown() {
87746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!can_send_events_ || !has_been_shown_)
87846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
87946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
8801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (CommandLine::ForCurrentProcess()->HasSwitch(::switches::kTestType)) {
88146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    app_window_contents_->DispatchWindowShownForTests();
88246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
88346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
88446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
8855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::CloseContents(WebContents* contents) {
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  native_app_window_->Close();
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool AppWindow::ShouldSuppressDialogs() { return true; }
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)content::ColorChooser* AppWindow::OpenColorChooser(
8925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WebContents* web_contents,
8935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SkColor initial_color,
8945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const std::vector<content::ColorSuggestion>& suggestions) {
8955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return app_delegate_->ShowColorChooser(web_contents, initial_color);
89690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
89790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::RunFileChooser(WebContents* tab,
8995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               const content::FileChooserParams& params) {
900c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (window_type_is_panel()) {
901c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Panels can't host a file dialog, abort. TODO(stevenjb): allow file
902c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // dialogs to be unhosted but still close with the owning web contents.
903c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // crbug.com/172502.
904c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(WARNING) << "File dialog opened by panel.";
905c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
906c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
907eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
9085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  app_delegate_->RunFileChooser(tab, params);
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool AppWindow::IsPopupOrPanel(const WebContents* source) const { return true; }
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::MoveContents(WebContents* source, const gfx::Rect& pos) {
9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  native_app_window_->SetBounds(pos);
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::NavigationStateChanged(const content::WebContents* source,
9186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                       content::InvalidateTypes changed_flags) {
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (changed_flags & content::INVALIDATE_TYPE_TITLE)
9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    native_app_window_->UpdateWindowTitle();
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (changed_flags & content::INVALIDATE_TYPE_TAB)
9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    native_app_window_->UpdateWindowIcon();
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::ToggleFullscreenModeForTab(content::WebContents* source,
9265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                           bool enter_fullscreen) {
9271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const Extension* extension = GetExtension();
928010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!extension)
929010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
930010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
931c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!IsExtensionWithPermissionOrSuggestInConsole(
932010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          APIPermission::kFullscreen, extension, source->GetRenderViewHost())) {
933c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
934c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SetFullscreen(FULLSCREEN_TYPE_HTML_API, enter_fullscreen);
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool AppWindow::IsFullscreenForTabOrPending(const content::WebContents* source)
9405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const {
9415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return IsHtmlApiFullscreen();
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
94434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)void AppWindow::Observe(int type,
94534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)                        const content::NotificationSource& source,
94634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)                        const content::NotificationDetails& details) {
94734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  switch (type) {
94834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)    case NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: {
94934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)      const Extension* unloaded_extension =
95034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)          content::Details<UnloadedExtensionInfo>(details)->extension;
95134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)      if (extension_id_ == unloaded_extension->id())
95234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)        native_app_window_->Close();
95334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)      break;
95434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)    }
95534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)    case NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED: {
95634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)      const Extension* installed_extension =
95734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)          content::Details<const InstalledExtensionInfo>(details)->extension;
95834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)      DCHECK(installed_extension);
95934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)      if (installed_extension->id() == extension_id())
96034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)        native_app_window_->UpdateShelfMenu();
96134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)      break;
96234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)    }
96334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)    default:
96434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)      NOTREACHED() << "Received unexpected notification";
96534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  }
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::SetWebContentsBlocked(content::WebContents* web_contents,
9695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      bool blocked) {
9705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  app_delegate_->SetWebContentsBlocked(web_contents, blocked);
971eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
972eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
9735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool AppWindow::IsWebContentsVisible(content::WebContents* web_contents) {
9745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return app_delegate_->IsWebContentsVisible(web_contents);
975eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
976eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
9775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WebContentsModalDialogHost* AppWindow::GetWebContentsModalDialogHost() {
978c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return native_app_window_.get();
979c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
980c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
9815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::SaveWindowPosition() {
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (window_key_.empty())
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!native_app_window_)
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  AppWindowGeometryCache* cache =
9881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      AppWindowGeometryCache::Get(browser_context());
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect bounds = native_app_window_->GetRestoredBounds();
991eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gfx::Rect screen_bounds =
992eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      gfx::Screen::GetNativeScreen()->GetDisplayMatching(bounds).work_area();
993b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  ui::WindowShowState window_state = native_app_window_->GetRestoredState();
9945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cache->SaveGeometry(
995010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      extension_id(), window_key_, bounds, screen_bounds, window_state);
996eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
997eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
9985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppWindow::AdjustBoundsToBeVisibleOnScreen(
999eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const gfx::Rect& cached_bounds,
1000eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const gfx::Rect& cached_screen_bounds,
1001eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const gfx::Rect& current_screen_bounds,
1002eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const gfx::Size& minimum_size,
1003eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    gfx::Rect* bounds) const {
1004eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  *bounds = cached_bounds;
1005eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1006eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Reposition and resize the bounds if the cached_screen_bounds is different
1007eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // from the current screen bounds and the current screen bounds doesn't
1008eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // completely contain the bounds.
1009a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (cached_screen_bounds != current_screen_bounds &&
1010eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      !current_screen_bounds.Contains(cached_bounds)) {
1011eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    bounds->set_width(
1012eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        std::max(minimum_size.width(),
1013eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 std::min(bounds->width(), current_screen_bounds.width())));
1014eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    bounds->set_height(
1015eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        std::max(minimum_size.height(),
1016eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 std::min(bounds->height(), current_screen_bounds.height())));
1017eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    bounds->set_x(
1018eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        std::max(current_screen_bounds.x(),
1019eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 std::min(bounds->x(),
1020eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          current_screen_bounds.right() - bounds->width())));
1021eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    bounds->set_y(
1022eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        std::max(current_screen_bounds.y(),
1023eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 std::min(bounds->y(),
1024eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          current_screen_bounds.bottom() - bounds->height())));
1025eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1028a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AppWindow::CreateParams AppWindow::LoadDefaults(CreateParams params)
10295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const {
1030a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Ensure width and height are specified.
1031a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (params.content_spec.bounds.width() == 0 &&
1032a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      params.window_spec.bounds.width() == 0) {
1033a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    params.content_spec.bounds.set_width(kDefaultWidth);
1034a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
1035a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (params.content_spec.bounds.height() == 0 &&
1036a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      params.window_spec.bounds.height() == 0) {
1037a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    params.content_spec.bounds.set_height(kDefaultHeight);
1038a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
10398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
10405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If left and top are left undefined, the native app window will center
10418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // the window on the main screen in a platform-defined manner.
10428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
10438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Load cached state if it exists.
10448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!params.window_key.empty()) {
10451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    AppWindowGeometryCache* cache =
10461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        AppWindowGeometryCache::Get(browser_context());
10478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
10488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    gfx::Rect cached_bounds;
10498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    gfx::Rect cached_screen_bounds;
10508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ui::WindowShowState cached_state = ui::SHOW_STATE_DEFAULT;
1051010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (cache->GetGeometry(extension_id(),
10525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           params.window_key,
10535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           &cached_bounds,
10545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           &cached_screen_bounds,
10558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                           &cached_state)) {
10568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // App window has cached screen bounds, make sure it fits on screen in
10578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // case the screen resolution changed.
10588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      gfx::Screen* screen = gfx::Screen::GetNativeScreen();
10598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      gfx::Display display = screen->GetDisplayMatching(cached_bounds);
10608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      gfx::Rect current_screen_bounds = display.work_area();
10611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      SizeConstraints constraints(params.GetWindowMinimumSize(gfx::Insets()),
10621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  params.GetWindowMaximumSize(gfx::Insets()));
10638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      AdjustBoundsToBeVisibleOnScreen(cached_bounds,
10648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                      cached_screen_bounds,
10658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                      current_screen_bounds,
1066a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                      constraints.GetMinimumSize(),
1067a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                      &params.window_spec.bounds);
10688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      params.state = cached_state;
1069a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1070a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // Since we are restoring a cached state, reset the content bounds spec to
1071a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // ensure it is not used.
1072a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      params.content_spec.ResetBounds();
10738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
10748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
10758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
10768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return params;
10778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
10788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
10805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SkRegion* AppWindow::RawDraggableRegionsToSkRegion(
10811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::vector<DraggableRegion>& regions) {
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkRegion* sk_region = new SkRegion;
10831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (std::vector<DraggableRegion>::const_iterator iter = regions.begin();
10845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       iter != regions.end();
10855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       ++iter) {
10861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const DraggableRegion& region = *iter;
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sk_region->op(
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        region.bounds.x(),
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        region.bounds.y(),
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        region.bounds.right(),
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        region.bounds.bottom(),
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op);
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sk_region;
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1096868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace extensions
1098