OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "apps/app_shim/extension_app_shim_handler_mac.h" | 5 #include "apps/app_shim/extension_app_shim_handler_mac.h" |
6 | 6 |
7 #include "apps/app_lifetime_monitor_factory.h" | 7 #include "apps/app_lifetime_monitor_factory.h" |
8 #include "apps/app_shim/app_shim_messages.h" | 8 #include "apps/app_shim/app_shim_messages.h" |
9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "chrome/browser/browser_process.h" | 11 #include "chrome/browser/browser_process.h" |
12 #include "chrome/browser/extensions/extension_host.h" | 12 #include "chrome/browser/extensions/extension_host.h" |
13 #include "chrome/browser/extensions/extension_service.h" | 13 #include "chrome/browser/extensions/extension_service.h" |
14 #include "chrome/browser/extensions/extension_system.h" | 14 #include "chrome/browser/extensions/extension_system.h" |
15 #include "chrome/browser/extensions/shell_window_registry.h" | 15 #include "chrome/browser/extensions/shell_window_registry.h" |
16 #include "chrome/browser/profiles/profile.h" | 16 #include "chrome/browser/profiles/profile.h" |
17 #include "chrome/browser/profiles/profile_manager.h" | 17 #include "chrome/browser/profiles/profile_manager.h" |
18 #include "chrome/browser/ui/extensions/application_launch.h" | 18 #include "chrome/browser/ui/extensions/application_launch.h" |
19 #include "chrome/browser/ui/extensions/native_app_window.h" | 19 #include "chrome/browser/ui/extensions/native_app_window.h" |
20 #include "chrome/browser/ui/extensions/shell_window.h" | 20 #include "chrome/browser/ui/extensions/shell_window.h" |
21 #include "chrome/browser/ui/web_applications/web_app_ui.h" | 21 #include "chrome/browser/ui/web_applications/web_app_ui.h" |
22 #include "chrome/browser/web_applications/web_app_mac.h" | 22 #include "chrome/browser/web_applications/web_app_mac.h" |
23 #include "chrome/common/chrome_notification_types.h" | 23 #include "chrome/common/chrome_notification_types.h" |
24 #include "content/public/browser/notification_details.h" | 24 #include "content/public/browser/notification_details.h" |
25 #include "content/public/browser/notification_service.h" | 25 #include "content/public/browser/notification_service.h" |
26 #include "content/public/browser/notification_source.h" | 26 #include "content/public/browser/notification_source.h" |
27 #include "ui/base/cocoa/focus_window_set.h" | 27 #include "ui/base/cocoa/focus_window_set.h" |
28 | 28 |
29 namespace { | 29 namespace apps { |
30 | 30 |
31 typedef extensions::ShellWindowRegistry::ShellWindowList ShellWindowList; | 31 typedef extensions::ShellWindowRegistry::ShellWindowList ShellWindowList; |
32 | 32 |
33 ShellWindowList GetWindows(Profile* profile, const std::string& extension_id) { | 33 bool ExtensionAppShimHandler::Delegate::ProfileExistsForPath( |
34 return extensions::ShellWindowRegistry::Get(profile)-> | |
35 GetShellWindowsForApp(extension_id); | |
36 } | |
37 | |
38 const extensions::Extension* GetExtension(Profile* profile, | |
39 const std::string& extension_id) { | |
40 return extensions::ExtensionSystem::Get(profile)->extension_service()-> | |
41 GetExtensionById(extension_id, false); | |
42 } | |
43 | |
44 } // namespace | |
45 | |
46 namespace apps { | |
47 | |
48 bool ExtensionAppShimHandler::ProfileManagerFacade::ProfileExistsForPath( | |
49 const base::FilePath& path) { | 34 const base::FilePath& path) { |
50 ProfileManager* profile_manager = g_browser_process->profile_manager(); | 35 ProfileManager* profile_manager = g_browser_process->profile_manager(); |
51 // Check for the profile name in the profile info cache to ensure that we | 36 // Check for the profile name in the profile info cache to ensure that we |
52 // never access any directory that isn't a known profile. | 37 // never access any directory that isn't a known profile. |
53 base::FilePath full_path = profile_manager->user_data_dir().Append(path); | 38 base::FilePath full_path = profile_manager->user_data_dir().Append(path); |
54 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); | 39 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); |
55 return cache.GetIndexOfProfileWithPath(full_path) != std::string::npos; | 40 return cache.GetIndexOfProfileWithPath(full_path) != std::string::npos; |
56 } | 41 } |
57 | 42 |
58 Profile* ExtensionAppShimHandler::ProfileManagerFacade::ProfileForPath( | 43 Profile* ExtensionAppShimHandler::Delegate::ProfileForPath( |
59 const base::FilePath& path) { | 44 const base::FilePath& path) { |
60 return g_browser_process->profile_manager()->GetProfile(path); | 45 return g_browser_process->profile_manager()->GetProfile(path); |
61 } | 46 } |
62 | 47 |
48 ShellWindowList ExtensionAppShimHandler::Delegate::GetWindows( | |
49 Profile* profile, | |
50 const std::string& extension_id) { | |
51 return extensions::ShellWindowRegistry::Get(profile)-> | |
52 GetShellWindowsForApp(extension_id); | |
53 } | |
54 | |
55 const extensions::Extension* | |
56 ExtensionAppShimHandler::Delegate::GetExtension( | |
tapted
2013/06/21 04:30:47
since the is_platform_app check is moving in here,
jackhou1
2013/06/21 05:46:27
Done.
| |
57 Profile* profile, | |
58 const std::string& extension_id) { | |
59 const extensions::Extension* extension = | |
60 extensions::ExtensionSystem::Get(profile)->extension_service()-> | |
tapted
2013/06/21 04:30:47
Should DCHECK here that that extension_service is
jackhou1
2013/06/21 05:46:27
Done.
| |
61 GetExtensionById(extension_id, false); | |
62 return extension && extension->is_platform_app() ? extension : NULL; | |
63 } | |
64 | |
65 content::WebContents* ExtensionAppShimHandler::Delegate::LaunchApp( | |
66 Profile* profile, | |
67 const extensions::Extension* extension) { | |
68 return chrome::OpenApplication(chrome::AppLaunchParams( | |
69 profile, extension, NEW_FOREGROUND_TAB)); | |
70 } | |
71 | |
72 void ExtensionAppShimHandler::Delegate::LaunchShim( | |
73 Profile* profile, | |
74 const extensions::Extension* extension) { | |
75 web_app::MaybeLaunchShortcut( | |
76 web_app::ShortcutInfoForExtensionAndProfile(extension, profile)); | |
77 } | |
78 | |
63 ExtensionAppShimHandler::ExtensionAppShimHandler() | 79 ExtensionAppShimHandler::ExtensionAppShimHandler() |
64 : profile_manager_facade_(new ProfileManagerFacade) { | 80 : delegate_(new Delegate) { |
65 // This is instantiated in BrowserProcessImpl::PreMainMessageLoopRun with | 81 // This is instantiated in BrowserProcessImpl::PreMainMessageLoopRun with |
66 // AppShimHostManager. Since PROFILE_CREATED is not fired until | 82 // AppShimHostManager. Since PROFILE_CREATED is not fired until |
67 // ProfileManager::GetLastUsedProfile/GetLastOpenedProfiles, this should catch | 83 // ProfileManager::GetLastUsedProfile/GetLastOpenedProfiles, this should catch |
68 // notifications for all profiles. | 84 // notifications for all profiles. |
69 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, | 85 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, |
70 content::NotificationService::AllBrowserContextsAndSources()); | 86 content::NotificationService::AllBrowserContextsAndSources()); |
71 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, | 87 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, |
72 content::NotificationService::AllBrowserContextsAndSources()); | 88 content::NotificationService::AllBrowserContextsAndSources()); |
73 } | 89 } |
74 | 90 |
75 ExtensionAppShimHandler::~ExtensionAppShimHandler() {} | 91 ExtensionAppShimHandler::~ExtensionAppShimHandler() {} |
76 | 92 |
77 bool ExtensionAppShimHandler::OnShimLaunch(Host* host, | 93 bool ExtensionAppShimHandler::OnShimLaunch(Host* host, |
78 AppShimLaunchType launch_type) { | 94 AppShimLaunchType launch_type) { |
79 const base::FilePath& profile_path = host->GetProfilePath(); | 95 const base::FilePath& profile_path = host->GetProfilePath(); |
80 DCHECK(!profile_path.empty()); | 96 DCHECK(!profile_path.empty()); |
81 | 97 |
82 if (!profile_manager_facade_->ProfileExistsForPath(profile_path)) { | 98 if (!delegate_->ProfileExistsForPath(profile_path)) { |
83 // User may have deleted the profile this shim was originally created for. | 99 // User may have deleted the profile this shim was originally created for. |
84 // TODO(jackhou): Add some UI for this case and remove the LOG. | 100 // TODO(jackhou): Add some UI for this case and remove the LOG. |
85 LOG(ERROR) << "Requested directory is not a known profile '" | 101 LOG(ERROR) << "Requested directory is not a known profile '" |
86 << profile_path.value() << "'."; | 102 << profile_path.value() << "'."; |
87 return false; | 103 return false; |
88 } | 104 } |
89 | 105 |
90 Profile* profile = profile_manager_facade_->ProfileForPath(profile_path); | 106 Profile* profile = delegate_->ProfileForPath(profile_path); |
91 | 107 |
92 const std::string& app_id = host->GetAppId(); | 108 const std::string& app_id = host->GetAppId(); |
93 if (!extensions::Extension::IdIsValid(app_id)) { | 109 if (!extensions::Extension::IdIsValid(app_id)) { |
94 LOG(ERROR) << "Bad app ID from app shim launch message."; | 110 LOG(ERROR) << "Bad app ID from app shim launch message."; |
95 return false; | 111 return false; |
96 } | 112 } |
97 | 113 |
98 // TODO(jackhou): Add some UI for this case and remove the LOG. | 114 // TODO(jackhou): Add some UI for this case and remove the LOG. |
99 if (!LaunchApp(profile, app_id, launch_type)) | 115 const extensions::Extension* extension = |
116 delegate_->GetExtension(profile, app_id); | |
117 if (!extension) { | |
118 LOG(ERROR) << "Attempted to launch nonexistent app with id '" | |
119 << app_id << "'."; | |
100 return false; | 120 return false; |
121 } | |
122 | |
123 if (launch_type == APP_SHIM_LAUNCH_REGISTER_ONLY && | |
tapted
2013/06/21 04:30:47
needs curlies if the condition is multi-line
jackhou1
2013/06/21 05:46:27
Done.
| |
124 delegate_->GetWindows(profile, app_id).empty()) | |
tapted
2013/06/21 04:30:47
Should this be !empty()?
Maybe a comment, like ~"
jackhou1
2013/06/21 05:46:27
It should be empty(), because it returns false if
| |
125 return false; | |
126 | |
127 // TODO(jeremya): Handle the case that launching the app fails. Probably we | |
128 // need to watch for 'app successfully launched' or at least 'background page | |
129 // exists/was created' and time out with failure if we don't see that sign of | |
130 // life within a certain window. | |
131 if (launch_type == APP_SHIM_LAUNCH_NORMAL) | |
132 delegate_->LaunchApp(profile, extension); | |
tapted
2013/06/21 04:30:47
Should it return false if LaunchApp returns NULL h
jackhou1
2013/06/21 05:46:27
Turns out LaunchApplication always returns NULL fo
| |
101 | 133 |
102 // The first host to claim this (profile, app_id) becomes the main host. | 134 // The first host to claim this (profile, app_id) becomes the main host. |
103 // For any others, focus the app and return false. | 135 // For any others, focus the app and return false. |
104 if (!hosts_.insert(make_pair(make_pair(profile, app_id), host)).second) { | 136 if (!hosts_.insert(make_pair(make_pair(profile, app_id), host)).second) { |
105 OnShimFocus(host); | 137 OnShimFocus(host); |
106 return false; | 138 return false; |
107 } | 139 } |
108 | 140 |
109 return true; | 141 return true; |
110 } | 142 } |
111 | 143 |
112 void ExtensionAppShimHandler::OnShimClose(Host* host) { | 144 void ExtensionAppShimHandler::OnShimClose(Host* host) { |
113 DCHECK(profile_manager_facade_->ProfileExistsForPath( | 145 DCHECK(delegate_->ProfileExistsForPath( |
tapted
2013/06/21 04:30:47
nit: can this fit on the line above now?
jackhou1
2013/06/21 05:46:27
Done.
| |
114 host->GetProfilePath())); | 146 host->GetProfilePath())); |
115 Profile* profile = | 147 Profile* profile = |
116 profile_manager_facade_->ProfileForPath(host->GetProfilePath()); | 148 delegate_->ProfileForPath(host->GetProfilePath()); |
tapted
2013/06/21 04:30:47
nit: one line?
up to 6 more below too
jackhou1
2013/06/21 05:46:27
Done.
| |
117 | 149 |
118 HostMap::iterator it = hosts_.find(make_pair(profile, host->GetAppId())); | 150 HostMap::iterator it = hosts_.find(make_pair(profile, host->GetAppId())); |
119 // Any hosts other than the main host will still call OnShimClose, so ignore | 151 // Any hosts other than the main host will still call OnShimClose, so ignore |
120 // them. | 152 // them. |
121 if (it != hosts_.end() && it->second == host) | 153 if (it != hosts_.end() && it->second == host) |
122 hosts_.erase(it); | 154 hosts_.erase(it); |
123 } | 155 } |
124 | 156 |
125 void ExtensionAppShimHandler::OnShimFocus(Host* host) { | 157 void ExtensionAppShimHandler::OnShimFocus(Host* host) { |
126 DCHECK(profile_manager_facade_->ProfileExistsForPath( | 158 DCHECK(delegate_->ProfileExistsForPath( |
127 host->GetProfilePath())); | 159 host->GetProfilePath())); |
128 Profile* profile = | 160 Profile* profile = |
129 profile_manager_facade_->ProfileForPath(host->GetProfilePath()); | 161 delegate_->ProfileForPath(host->GetProfilePath()); |
130 | 162 |
131 const ShellWindowList windows = GetWindows(profile, host->GetAppId()); | 163 const ShellWindowList windows = |
164 delegate_->GetWindows(profile, host->GetAppId()); | |
132 std::set<gfx::NativeWindow> native_windows; | 165 std::set<gfx::NativeWindow> native_windows; |
133 for (ShellWindowList::const_iterator it = windows.begin(); | 166 for (ShellWindowList::const_iterator it = windows.begin(); |
134 it != windows.end(); ++it) { | 167 it != windows.end(); ++it) { |
135 native_windows.insert((*it)->GetNativeWindow()); | 168 native_windows.insert((*it)->GetNativeWindow()); |
136 } | 169 } |
137 ui::FocusWindowSet(native_windows); | 170 ui::FocusWindowSet(native_windows); |
138 } | 171 } |
139 | 172 |
140 void ExtensionAppShimHandler::OnShimQuit(Host* host) { | 173 void ExtensionAppShimHandler::OnShimQuit(Host* host) { |
141 DCHECK(profile_manager_facade_->ProfileExistsForPath( | 174 DCHECK(delegate_->ProfileExistsForPath( |
142 host->GetProfilePath())); | 175 host->GetProfilePath())); |
143 Profile* profile = | 176 Profile* profile = |
144 profile_manager_facade_->ProfileForPath(host->GetProfilePath()); | 177 delegate_->ProfileForPath(host->GetProfilePath()); |
145 | 178 |
146 const ShellWindowList windows = GetWindows(profile, host->GetAppId()); | 179 const ShellWindowList windows = |
180 delegate_->GetWindows(profile, host->GetAppId()); | |
147 for (extensions::ShellWindowRegistry::const_iterator it = windows.begin(); | 181 for (extensions::ShellWindowRegistry::const_iterator it = windows.begin(); |
148 it != windows.end(); ++it) { | 182 it != windows.end(); ++it) { |
149 (*it)->GetBaseWindow()->Close(); | 183 (*it)->GetBaseWindow()->Close(); |
150 } | 184 } |
151 } | 185 } |
152 | 186 |
153 void ExtensionAppShimHandler::set_profile_manager_facade( | 187 void ExtensionAppShimHandler::set_dependency_facade( |
154 ProfileManagerFacade* profile_manager_facade) { | 188 Delegate* dependency_facade) { |
155 profile_manager_facade_.reset(profile_manager_facade); | 189 delegate_.reset(dependency_facade); |
156 } | |
157 | |
158 bool ExtensionAppShimHandler::LaunchApp(Profile* profile, | |
159 const std::string& app_id, | |
160 AppShimLaunchType launch_type) { | |
161 const extensions::Extension* extension = GetExtension(profile, app_id); | |
162 if (!extension) { | |
163 LOG(ERROR) << "Attempted to launch nonexistent app with id '" | |
164 << app_id << "'."; | |
165 return false; | |
166 } | |
167 | |
168 if (launch_type == APP_SHIM_LAUNCH_REGISTER_ONLY) | |
169 return !GetWindows(profile, app_id).empty(); | |
170 | |
171 // TODO(jeremya): Handle the case that launching the app fails. Probably we | |
172 // need to watch for 'app successfully launched' or at least 'background page | |
173 // exists/was created' and time out with failure if we don't see that sign of | |
174 // life within a certain window. | |
175 chrome::OpenApplication(chrome::AppLaunchParams( | |
176 profile, extension, NEW_FOREGROUND_TAB)); | |
177 return true; | |
178 } | 190 } |
179 | 191 |
180 void ExtensionAppShimHandler::Observe( | 192 void ExtensionAppShimHandler::Observe( |
181 int type, | 193 int type, |
182 const content::NotificationSource& source, | 194 const content::NotificationSource& source, |
183 const content::NotificationDetails& details) { | 195 const content::NotificationDetails& details) { |
184 Profile* profile = content::Source<Profile>(source).ptr(); | 196 Profile* profile = content::Source<Profile>(source).ptr(); |
185 if (profile->IsOffTheRecord()) | 197 if (profile->IsOffTheRecord()) |
186 return; | 198 return; |
187 | 199 |
(...skipping 16 matching lines...) Expand all Loading... | |
204 NOTREACHED(); // Unexpected notification. | 216 NOTREACHED(); // Unexpected notification. |
205 break; | 217 break; |
206 } | 218 } |
207 } | 219 } |
208 | 220 |
209 void ExtensionAppShimHandler::OnAppStart(Profile* profile, | 221 void ExtensionAppShimHandler::OnAppStart(Profile* profile, |
210 const std::string& app_id) {} | 222 const std::string& app_id) {} |
211 | 223 |
212 void ExtensionAppShimHandler::OnAppActivated(Profile* profile, | 224 void ExtensionAppShimHandler::OnAppActivated(Profile* profile, |
213 const std::string& app_id) { | 225 const std::string& app_id) { |
214 const extensions::Extension* extension = GetExtension(profile, app_id); | 226 const extensions::Extension* extension = |
215 if (!extension || !extension->is_platform_app()) | 227 delegate_->GetExtension(profile, app_id); |
228 if (!extension) | |
216 return; | 229 return; |
217 | 230 |
218 if (hosts_.count(make_pair(profile, extension->id()))) | 231 if (hosts_.count(make_pair(profile, app_id))) |
219 return; | 232 return; |
220 | 233 |
221 web_app::MaybeLaunchShortcut( | 234 delegate_->LaunchShim(profile, extension); |
222 web_app::ShortcutInfoForExtensionAndProfile(extension, profile)); | |
223 } | 235 } |
224 | 236 |
225 void ExtensionAppShimHandler::OnAppDeactivated(Profile* profile, | 237 void ExtensionAppShimHandler::OnAppDeactivated(Profile* profile, |
226 const std::string& app_id) { | 238 const std::string& app_id) { |
227 HostMap::const_iterator it = hosts_.find(make_pair(profile, app_id)); | 239 HostMap::const_iterator it = hosts_.find(make_pair(profile, app_id)); |
228 if (it != hosts_.end()) | 240 if (it != hosts_.end()) |
229 it->second->OnAppClosed(); | 241 it->second->OnAppClosed(); |
230 } | 242 } |
231 | 243 |
232 void ExtensionAppShimHandler::OnAppStop(Profile* profile, | 244 void ExtensionAppShimHandler::OnAppStop(Profile* profile, |
233 const std::string& app_id) {} | 245 const std::string& app_id) {} |
234 | 246 |
235 void ExtensionAppShimHandler::OnChromeTerminating() {} | 247 void ExtensionAppShimHandler::OnChromeTerminating() {} |
236 | 248 |
237 } // namespace apps | 249 } // namespace apps |
OLD | NEW |