1 // Copyright 2015 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/developer_private/inspectable_views_finder.h"
7 #include "chrome/browser/profiles/profile.h"
8 #include "chrome/common/extensions/api/developer_private.h"
9 #include "content/public/browser/render_frame_host.h"
10 #include "content/public/browser/render_process_host.h"
11 #include "content/public/browser/web_contents.h"
12 #include "extensions/browser/app_window/app_window.h"
13 #include "extensions/browser/app_window/app_window_registry.h"
14 #include "extensions/browser/extension_host.h"
15 #include "extensions/browser/process_manager.h"
16 #include "extensions/browser/view_type_utils.h"
17 #include "extensions/common/constants.h"
18 #include "extensions/common/extension.h"
19 #include "extensions/common/manifest_handlers/background_info.h"
22 namespace extensions
{
24 InspectableViewsFinder::InspectableViewsFinder(Profile
* profile
)
28 InspectableViewsFinder::~InspectableViewsFinder() {
32 InspectableViewsFinder::View
InspectableViewsFinder::ConstructView(
34 int render_process_id
,
38 linked_ptr
<api::developer_private::ExtensionView
> view(
39 new api::developer_private::ExtensionView());
40 view
->url
= url
.spec();
41 view
->render_process_id
= render_process_id
;
42 // NOTE(devlin): This is called "render_view_id" in the api for legacy
43 // reasons, but it's not a high priority to change.
44 view
->render_view_id
= render_frame_id
;
45 view
->incognito
= incognito
;
47 case VIEW_TYPE_APP_WINDOW
:
48 view
->type
= api::developer_private::VIEW_TYPE_APP_WINDOW
;
50 case VIEW_TYPE_BACKGROUND_CONTENTS
:
51 view
->type
= api::developer_private::VIEW_TYPE_BACKGROUND_CONTENTS
;
53 case VIEW_TYPE_EXTENSION_BACKGROUND_PAGE
:
54 view
->type
= api::developer_private::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE
;
56 case VIEW_TYPE_EXTENSION_DIALOG
:
57 view
->type
= api::developer_private::VIEW_TYPE_EXTENSION_DIALOG
;
59 case VIEW_TYPE_EXTENSION_POPUP
:
60 view
->type
= api::developer_private::VIEW_TYPE_EXTENSION_POPUP
;
62 case VIEW_TYPE_LAUNCHER_PAGE
:
63 view
->type
= api::developer_private::VIEW_TYPE_LAUNCHER_PAGE
;
66 view
->type
= api::developer_private::VIEW_TYPE_PANEL
;
68 case VIEW_TYPE_TAB_CONTENTS
:
69 view
->type
= api::developer_private::VIEW_TYPE_TAB_CONTENTS
;
71 case VIEW_TYPE_VIRTUAL_KEYBOARD
:
72 view
->type
= api::developer_private::VIEW_TYPE_VIRTUAL_KEYBOARD
;
80 InspectableViewsFinder::ViewList
InspectableViewsFinder::GetViewsForExtension(
81 const Extension
& extension
,
84 GetViewsForExtensionForProfile(
85 extension
, profile_
, is_enabled
, false, &result
);
86 if (profile_
->HasOffTheRecordProfile()) {
87 GetViewsForExtensionForProfile(
89 profile_
->GetOffTheRecordProfile(),
98 void InspectableViewsFinder::GetViewsForExtensionForProfile(
99 const Extension
& extension
,
104 ProcessManager
* process_manager
= ProcessManager::Get(profile
);
105 // Get the extension process's active views.
106 GetViewsForExtensionProcess(extension
,
110 // Get app window views, if not incognito.
112 GetAppWindowViewsForExtension(extension
, result
);
113 // Include a link to start the lazy background page, if applicable.
114 if (BackgroundInfo::HasLazyBackgroundPage(&extension
) &&
116 !process_manager
->GetBackgroundHostForExtension(extension
.id())) {
117 result
->push_back(ConstructView(
118 BackgroundInfo::GetBackgroundURL(&extension
),
122 VIEW_TYPE_EXTENSION_BACKGROUND_PAGE
));
126 void InspectableViewsFinder::GetViewsForExtensionProcess(
127 const Extension
& extension
,
128 ProcessManager
* process_manager
,
131 const std::set
<content::RenderFrameHost
*>& hosts
=
132 process_manager
->GetRenderFrameHostsForExtension(extension
.id());
133 for (content::RenderFrameHost
* host
: hosts
) {
134 content::WebContents
* web_contents
=
135 content::WebContents::FromRenderFrameHost(host
);
136 ViewType host_type
= GetViewType(web_contents
);
137 if (host_type
== VIEW_TYPE_EXTENSION_POPUP
||
138 host_type
== VIEW_TYPE_EXTENSION_DIALOG
) {
142 GURL url
= web_contents
->GetURL();
143 // If this is a background page that just opened, there might not be a
144 // committed (or visible) url yet. In this case, use the initial url.
145 if (url
.is_empty()) {
146 ExtensionHost
* extension_host
=
147 process_manager
->GetExtensionHostForRenderFrameHost(host
);
149 url
= extension_host
->initial_url();
152 content::RenderProcessHost
* process
= host
->GetProcess();
153 result
->push_back(ConstructView(url
, process
->GetID(), host
->GetRoutingID(),
154 is_incognito
, host_type
));
158 void InspectableViewsFinder::GetAppWindowViewsForExtension(
159 const Extension
& extension
,
161 AppWindowRegistry
* registry
= AppWindowRegistry::Get(profile_
);
165 AppWindowRegistry::AppWindowList windows
=
166 registry
->GetAppWindowsForApp(extension
.id());
168 for (const AppWindow
* window
: windows
) {
169 content::WebContents
* web_contents
= window
->web_contents();
171 // If the window just opened, there might not be a committed (or visible)
172 // url yet. In this case, use the initial url.
173 GURL url
= web_contents
->GetLastCommittedURL();
175 url
= window
->initial_url();
177 content::RenderProcessHost
* process
= web_contents
->GetRenderProcessHost();
178 result
->push_back(ConstructView(
179 url
, process
->GetID(), web_contents
->GetMainFrame()->GetRoutingID(),
180 false, GetViewType(web_contents
)));
184 } // namespace extensions