1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/tabs/ash_panel_contents.h"
7 #include "apps/ui/native_app_window.h"
8 #include "base/values.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
11 #include "chrome/browser/extensions/api/tabs/tabs_windows_api.h"
12 #include "chrome/browser/extensions/api/tabs/windows_event_router.h"
13 #include "chrome/browser/extensions/extension_tab_util.h"
14 #include "chrome/browser/extensions/window_controller_list.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/sessions/session_tab_helper.h"
17 #include "content/public/browser/browser_context.h"
18 #include "content/public/browser/site_instance.h"
19 #include "content/public/browser/web_contents.h"
20 #include "extensions/common/extension.h"
21 #include "extensions/common/extension_messages.h"
22 #include "ui/gfx/image/image.h"
24 using apps::AppWindow
;
25 using apps::NativeAppWindow
;
27 // AshPanelWindowController ----------------------------------------------------
29 // This class enables an AppWindow instance to be accessed (to a limited
30 // extent) via the chrome.windows and chrome.tabs API. This is a temporary
31 // bridge to support instantiating AppWindows from v1 apps, specifically
32 // for creating Panels in Ash. See crbug.com/160645.
33 class AshPanelWindowController
: public extensions::WindowController
{
35 AshPanelWindowController(AppWindow
* window
, Profile
* profile
);
36 virtual ~AshPanelWindowController();
38 void NativeWindowChanged();
40 // Overridden from extensions::WindowController.
41 virtual int GetWindowId() const OVERRIDE
;
42 virtual std::string
GetWindowTypeText() const OVERRIDE
;
43 virtual base::DictionaryValue
* CreateWindowValueWithTabs(
44 const extensions::Extension
* extension
) const OVERRIDE
;
45 virtual base::DictionaryValue
* CreateTabValue(
46 const extensions::Extension
* extension
, int tab_index
) const OVERRIDE
;
47 virtual bool CanClose(Reason
* reason
) const OVERRIDE
;
48 virtual void SetFullscreenMode(bool is_fullscreen
,
49 const GURL
& extension_url
) const OVERRIDE
;
50 virtual bool IsVisibleToExtension(
51 const extensions::Extension
* extension
) const OVERRIDE
;
54 AppWindow
* app_window_
; // Weak pointer; this is owned by app_window_
57 DISALLOW_COPY_AND_ASSIGN(AshPanelWindowController
);
60 AshPanelWindowController::AshPanelWindowController(AppWindow
* app_window
,
62 : extensions::WindowController(app_window
->GetBaseWindow(), profile
),
63 app_window_(app_window
),
64 is_active_(app_window
->GetBaseWindow()->IsActive()) {
65 extensions::WindowControllerList::GetInstance()->AddExtensionWindow(this);
68 AshPanelWindowController::~AshPanelWindowController() {
69 extensions::WindowControllerList::GetInstance()->RemoveExtensionWindow(this);
72 int AshPanelWindowController::GetWindowId() const {
73 return static_cast<int>(app_window_
->session_id().id());
76 std::string
AshPanelWindowController::GetWindowTypeText() const {
77 return extensions::tabs_constants::kWindowTypeValuePanel
;
80 base::DictionaryValue
* AshPanelWindowController::CreateWindowValueWithTabs(
81 const extensions::Extension
* extension
) const {
82 DCHECK(IsVisibleToExtension(extension
));
83 base::DictionaryValue
* result
= CreateWindowValue();
84 base::DictionaryValue
* tab_value
= CreateTabValue(extension
, 0);
86 base::ListValue
* tab_list
= new base::ListValue();
87 tab_list
->Append(tab_value
);
88 result
->Set(extensions::tabs_constants::kTabsKey
, tab_list
);
93 base::DictionaryValue
* AshPanelWindowController::CreateTabValue(
94 const extensions::Extension
* extension
, int tab_index
) const {
95 if ((extension
&& !IsVisibleToExtension(extension
)) ||
99 content::WebContents
* web_contents
= app_window_
->web_contents();
103 base::DictionaryValue
* tab_value
= new base::DictionaryValue();
104 tab_value
->SetInteger(extensions::tabs_constants::kIdKey
,
105 SessionID::IdForTab(web_contents
));
106 tab_value
->SetInteger(extensions::tabs_constants::kIndexKey
, 0);
107 const int window_id
= GetWindowId();
108 tab_value
->SetInteger(extensions::tabs_constants::kWindowIdKey
, window_id
);
109 tab_value
->SetString(
110 extensions::tabs_constants::kUrlKey
, web_contents
->GetURL().spec());
111 tab_value
->SetString(
112 extensions::tabs_constants::kStatusKey
,
113 extensions::ExtensionTabUtil::GetTabStatusText(
114 web_contents
->IsLoading()));
115 tab_value
->SetBoolean(extensions::tabs_constants::kActiveKey
,
116 app_window_
->GetBaseWindow()->IsActive());
117 // AppWindow only ever contains one tab, so that tab is always effectively
118 // selcted and highlighted (for purposes of the chrome.tabs API).
119 tab_value
->SetInteger(extensions::tabs_constants::kWindowIdKey
, window_id
);
120 tab_value
->SetInteger(extensions::tabs_constants::kIdKey
, window_id
);
121 tab_value
->SetBoolean(extensions::tabs_constants::kSelectedKey
, true);
122 tab_value
->SetBoolean(extensions::tabs_constants::kHighlightedKey
, true);
123 tab_value
->SetBoolean(extensions::tabs_constants::kPinnedKey
, false);
124 tab_value
->SetString(
125 extensions::tabs_constants::kTitleKey
, web_contents
->GetTitle());
126 tab_value
->SetBoolean(
127 extensions::tabs_constants::kIncognitoKey
,
128 web_contents
->GetBrowserContext()->IsOffTheRecord());
132 bool AshPanelWindowController::CanClose(Reason
* reason
) const {
136 void AshPanelWindowController::SetFullscreenMode(
137 bool is_fullscreen
, const GURL
& extension_url
) const {
138 // Do nothing. Panels cannot be fullscreen.
141 bool AshPanelWindowController::IsVisibleToExtension(
142 const extensions::Extension
* extension
) const {
143 return app_window_
->extension() &&
144 extension
->id() == app_window_
->extension()->id();
147 void AshPanelWindowController::NativeWindowChanged() {
148 bool active
= app_window_
->GetBaseWindow()->IsActive();
149 if (active
== is_active_
)
152 // Let the extension API know that the active window changed.
153 extensions::TabsWindowsAPI
* tabs_windows_api
=
154 extensions::TabsWindowsAPI::Get(profile());
155 if (!tabs_windows_api
)
157 tabs_windows_api
->windows_event_router()->OnActiveWindowChanged(
158 active
? this : NULL
);
161 // AshPanelContents -----------------------------------------------------
163 AshPanelContents::AshPanelContents(AppWindow
* host
) : host_(host
) {}
165 AshPanelContents::~AshPanelContents() {
168 void AshPanelContents::Initialize(content::BrowserContext
* context
,
172 extension_function_dispatcher_
.reset(
173 new ExtensionFunctionDispatcher(context
, this));
176 content::WebContents::Create(content::WebContents::CreateParams(
177 context
, content::SiteInstance::CreateForURL(context
, url_
))));
179 // Needed to give the web contents a Window ID. Extension APIs expect web
180 // contents to have a Window ID. Also required for FaviconTabHelper to
181 // correctly set the window icon and title.
182 SessionTabHelper::CreateForWebContents(web_contents_
.get());
183 SessionTabHelper::FromWebContents(web_contents_
.get())->SetWindowID(
184 host_
->session_id());
186 // Responsible for loading favicons for the Launcher, which uses different
187 // logic than the FaviconTabHelper associated with web_contents_
188 // (instantiated in AppWindow::Init())
189 launcher_favicon_loader_
.reset(
190 new LauncherFaviconLoader(this, web_contents_
.get()));
192 content::WebContentsObserver::Observe(web_contents_
.get());
195 void AshPanelContents::LoadContents(int32 creator_process_id
) {
196 // This must be created after the native window has been created.
197 window_controller_
.reset(new AshPanelWindowController(
198 host_
, Profile::FromBrowserContext(host_
->browser_context())));
200 web_contents_
->GetController().LoadURL(
201 url_
, content::Referrer(), content::PAGE_TRANSITION_LINK
,
205 void AshPanelContents::NativeWindowChanged(NativeAppWindow
* native_app_window
) {
206 if (window_controller_
)
207 window_controller_
->NativeWindowChanged();
210 void AshPanelContents::NativeWindowClosed() {
213 content::WebContents
* AshPanelContents::GetWebContents() const {
214 return web_contents_
.get();
217 void AshPanelContents::FaviconUpdated() {
218 gfx::Image new_image
= gfx::Image::CreateFrom1xBitmap(
219 launcher_favicon_loader_
->GetFavicon());
220 host_
->UpdateAppIcon(new_image
);
223 bool AshPanelContents::OnMessageReceived(const IPC::Message
& message
) {
225 IPC_BEGIN_MESSAGE_MAP(AshPanelContents
, message
)
226 IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request
, OnRequest
)
227 IPC_MESSAGE_UNHANDLED(handled
= false)
228 IPC_END_MESSAGE_MAP()
232 extensions::WindowController
*
233 AshPanelContents::GetExtensionWindowController() const {
234 return window_controller_
.get();
237 content::WebContents
* AshPanelContents::GetAssociatedWebContents() const {
238 return web_contents_
.get();
241 void AshPanelContents::OnRequest(
242 const ExtensionHostMsg_Request_Params
& params
) {
243 extension_function_dispatcher_
->Dispatch(
244 params
, web_contents_
->GetRenderViewHost());