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_host_manager_mac.h" | 8 #include "apps/app_shim/app_shim_host_manager_mac.h" |
9 #include "apps/app_shim/app_shim_messages.h" | 9 #include "apps/app_shim/app_shim_messages.h" |
10 #include "apps/launcher.h" | 10 #include "apps/launcher.h" |
11 #include "apps/shell_window.h" | 11 #include "apps/shell_window.h" |
12 #include "apps/shell_window_registry.h" | 12 #include "apps/shell_window_registry.h" |
13 #include "apps/ui/native_app_window.h" | 13 #include "apps/ui/native_app_window.h" |
14 #include "base/files/file_path.h" | 14 #include "base/files/file_path.h" |
15 #include "base/logging.h" | 15 #include "base/logging.h" |
16 #include "chrome/browser/browser_process.h" | 16 #include "chrome/browser/browser_process.h" |
17 #include "chrome/browser/chrome_notification_types.h" | 17 #include "chrome/browser/chrome_notification_types.h" |
18 #include "chrome/browser/extensions/extension_host.h" | 18 #include "chrome/browser/extensions/extension_host.h" |
19 #include "chrome/browser/extensions/extension_service.h" | 19 #include "chrome/browser/extensions/extension_service.h" |
20 #include "chrome/browser/extensions/extension_system.h" | 20 #include "chrome/browser/extensions/extension_system.h" |
21 #include "chrome/browser/profiles/profile.h" | 21 #include "chrome/browser/profiles/profile.h" |
22 #include "chrome/browser/profiles/profile_manager.h" | 22 #include "chrome/browser/profiles/profile_manager.h" |
23 #include "chrome/browser/ui/extensions/extension_enable_flow.h" | |
24 #include "chrome/browser/ui/extensions/extension_enable_flow_delegate.h" | |
23 #include "chrome/browser/ui/web_applications/web_app_ui.h" | 25 #include "chrome/browser/ui/web_applications/web_app_ui.h" |
24 #include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h" | 26 #include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h" |
25 #include "chrome/browser/web_applications/web_app_mac.h" | 27 #include "chrome/browser/web_applications/web_app_mac.h" |
26 #include "chrome/common/extensions/extension_constants.h" | 28 #include "chrome/common/extensions/extension_constants.h" |
27 #include "content/public/browser/notification_details.h" | 29 #include "content/public/browser/notification_details.h" |
28 #include "content/public/browser/notification_service.h" | 30 #include "content/public/browser/notification_service.h" |
29 #include "content/public/browser/notification_source.h" | 31 #include "content/public/browser/notification_source.h" |
30 #include "ui/base/cocoa/focus_window_set.h" | 32 #include "ui/base/cocoa/focus_window_set.h" |
31 | 33 |
32 namespace { | 34 namespace { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
66 it != windows.end(); ++it) { | 68 it != windows.end(); ++it) { |
67 native_windows.insert((*it)->GetNativeWindow()); | 69 native_windows.insert((*it)->GetNativeWindow()); |
68 } | 70 } |
69 // Allow workspace switching. For the browser process, we can reasonably rely | 71 // Allow workspace switching. For the browser process, we can reasonably rely |
70 // on OS X to switch spaces for us and honor relevant user settings. But shims | 72 // on OS X to switch spaces for us and honor relevant user settings. But shims |
71 // don't have windows, so we have to do it ourselves. | 73 // don't have windows, so we have to do it ourselves. |
72 ui::FocusWindowSet(native_windows, true); | 74 ui::FocusWindowSet(native_windows, true); |
73 return true; | 75 return true; |
74 } | 76 } |
75 | 77 |
78 // Attempts to launch a packaged app, prompting the user to enable it if | |
79 // necessary. The prompt is shown in its own window. | |
80 // This class manages its own lifetime. | |
81 class EnableViaPrompt : public ExtensionEnableFlowDelegate { | |
82 public: | |
83 EnableViaPrompt(Profile* profile, | |
84 const std::string& extension_id, | |
85 const base::Callback<void()>& callback) | |
86 : profile_(profile), | |
87 extension_id_(extension_id), | |
88 callback_(callback) { | |
89 } | |
90 | |
91 virtual ~EnableViaPrompt() { | |
92 } | |
93 | |
94 void Run() { | |
95 flow_.reset(new ExtensionEnableFlow(profile_, extension_id_, this)); | |
96 flow_->StartForCurrentlyNonexistentWindow( | |
97 base::Callback<gfx::NativeWindow(void)>()); | |
98 } | |
99 | |
100 private: | |
101 // ExtensionEnableFlowDelegate overrides. | |
102 virtual void ExtensionEnableFlowFinished() OVERRIDE { | |
103 callback_.Run(); | |
104 delete this; | |
105 } | |
106 | |
107 virtual void ExtensionEnableFlowAborted(bool user_initiated) OVERRIDE { | |
108 callback_.Run(); | |
109 delete this; | |
110 } | |
111 | |
112 Profile* profile_; | |
113 std::string extension_id_; | |
114 base::Callback<void()> callback_; | |
115 scoped_ptr<ExtensionEnableFlow> flow_; | |
116 | |
117 DISALLOW_COPY_AND_ASSIGN(EnableViaPrompt); | |
118 }; | |
119 | |
76 } // namespace | 120 } // namespace |
77 | 121 |
78 namespace apps { | 122 namespace apps { |
79 | 123 |
80 bool ExtensionAppShimHandler::Delegate::ProfileExistsForPath( | 124 bool ExtensionAppShimHandler::Delegate::ProfileExistsForPath( |
81 const base::FilePath& path) { | 125 const base::FilePath& path) { |
82 ProfileManager* profile_manager = g_browser_process->profile_manager(); | 126 ProfileManager* profile_manager = g_browser_process->profile_manager(); |
83 // Check for the profile name in the profile info cache to ensure that we | 127 // Check for the profile name in the profile info cache to ensure that we |
84 // never access any directory that isn't a known profile. | 128 // never access any directory that isn't a known profile. |
85 base::FilePath full_path = profile_manager->user_data_dir().Append(path); | 129 base::FilePath full_path = profile_manager->user_data_dir().Append(path); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
119 Profile* profile, | 163 Profile* profile, |
120 const std::string& extension_id) { | 164 const std::string& extension_id) { |
121 ExtensionService* extension_service = | 165 ExtensionService* extension_service = |
122 extensions::ExtensionSystem::Get(profile)->extension_service(); | 166 extensions::ExtensionSystem::Get(profile)->extension_service(); |
123 DCHECK(extension_service); | 167 DCHECK(extension_service); |
124 const extensions::Extension* extension = | 168 const extensions::Extension* extension = |
125 extension_service->GetExtensionById(extension_id, false); | 169 extension_service->GetExtensionById(extension_id, false); |
126 return extension && extension->is_platform_app() ? extension : NULL; | 170 return extension && extension->is_platform_app() ? extension : NULL; |
127 } | 171 } |
128 | 172 |
173 void ExtensionAppShimHandler::Delegate::EnableExtension( | |
174 Profile* profile, | |
175 const std::string& extension_id, | |
176 const base::Callback<void()>& callback) { | |
177 (new EnableViaPrompt(profile, extension_id, callback))->Run(); | |
178 } | |
179 | |
129 void ExtensionAppShimHandler::Delegate::LaunchApp( | 180 void ExtensionAppShimHandler::Delegate::LaunchApp( |
130 Profile* profile, | 181 Profile* profile, |
131 const extensions::Extension* extension, | 182 const extensions::Extension* extension, |
132 const std::vector<base::FilePath>& files) { | 183 const std::vector<base::FilePath>& files) { |
133 CoreAppLauncherHandler::RecordAppLaunchType( | 184 CoreAppLauncherHandler::RecordAppLaunchType( |
134 extension_misc::APP_LAUNCH_CMD_LINE_APP, extension->GetType()); | 185 extension_misc::APP_LAUNCH_CMD_LINE_APP, extension->GetType()); |
135 if (files.empty()) { | 186 if (files.empty()) { |
136 apps::LaunchPlatformApp(profile, extension); | 187 apps::LaunchPlatformApp(profile, extension); |
137 } else { | 188 } else { |
138 for (std::vector<base::FilePath>::const_iterator it = files.begin(); | 189 for (std::vector<base::FilePath>::const_iterator it = files.begin(); |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
279 | 330 |
280 // Return now. OnAppLaunchComplete will be called when the app is activated. | 331 // Return now. OnAppLaunchComplete will be called when the app is activated. |
281 } | 332 } |
282 | 333 |
283 void ExtensionAppShimHandler::OnProfileLoaded( | 334 void ExtensionAppShimHandler::OnProfileLoaded( |
284 Host* host, | 335 Host* host, |
285 AppShimLaunchType launch_type, | 336 AppShimLaunchType launch_type, |
286 const std::vector<base::FilePath>& files, | 337 const std::vector<base::FilePath>& files, |
287 Profile* profile) { | 338 Profile* profile) { |
288 const std::string& app_id = host->GetAppId(); | 339 const std::string& app_id = host->GetAppId(); |
289 // TODO(jackhou): Add some UI for this case and remove the LOG. | |
290 const extensions::Extension* extension = | |
291 delegate_->GetAppExtension(profile, app_id); | |
292 if (!extension) { | |
293 LOG(ERROR) << "Attempted to launch nonexistent app with id '" | |
294 << app_id << "'."; | |
295 host->OnAppLaunchComplete(APP_SHIM_LAUNCH_APP_NOT_FOUND); | |
296 return; | |
297 } | |
298 | 340 |
299 // The first host to claim this (profile, app_id) becomes the main host. | 341 // The first host to claim this (profile, app_id) becomes the main host. |
300 // For any others, focus or relaunch the app. | 342 // For any others, focus or relaunch the app. |
301 if (!hosts_.insert(make_pair(make_pair(profile, app_id), host)).second) { | 343 if (!hosts_.insert(make_pair(make_pair(profile, app_id), host)).second) { |
302 OnShimFocus(host, | 344 OnShimFocus(host, |
303 launch_type == APP_SHIM_LAUNCH_NORMAL ? | 345 launch_type == APP_SHIM_LAUNCH_NORMAL ? |
304 APP_SHIM_FOCUS_REOPEN : APP_SHIM_FOCUS_NORMAL, | 346 APP_SHIM_FOCUS_REOPEN : APP_SHIM_FOCUS_NORMAL, |
305 files); | 347 files); |
306 host->OnAppLaunchComplete(APP_SHIM_LAUNCH_DUPLICATE_HOST); | 348 host->OnAppLaunchComplete(APP_SHIM_LAUNCH_DUPLICATE_HOST); |
307 return; | 349 return; |
308 } | 350 } |
309 | 351 |
352 if (launch_type != APP_SHIM_LAUNCH_NORMAL) { | |
353 host->OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS); | |
354 return; | |
355 } | |
356 | |
310 // TODO(jeremya): Handle the case that launching the app fails. Probably we | 357 // TODO(jeremya): Handle the case that launching the app fails. Probably we |
311 // need to watch for 'app successfully launched' or at least 'background page | 358 // need to watch for 'app successfully launched' or at least 'background page |
312 // exists/was created' and time out with failure if we don't see that sign of | 359 // exists/was created' and time out with failure if we don't see that sign of |
313 // life within a certain window. | 360 // life within a certain window. |
314 if (launch_type == APP_SHIM_LAUNCH_NORMAL) | 361 const extensions::Extension* extension = |
362 delegate_->GetAppExtension(profile, app_id); | |
363 if (extension) { | |
315 delegate_->LaunchApp(profile, extension, files); | 364 delegate_->LaunchApp(profile, extension, files); |
316 else | 365 return; |
317 host->OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS); | 366 } |
367 | |
368 delegate_->EnableExtension( | |
369 profile, app_id, | |
370 base::Bind(&ExtensionAppShimHandler::OnExtensionEnabled, | |
371 weak_factory_.GetWeakPtr(), | |
372 host, profile, files)); | |
tapted
2013/12/12 02:41:21
profile.. might be OK. But is it safe to reference
jackhou1
2013/12/13 03:47:10
Done.
| |
318 } | 373 } |
319 | 374 |
375 void ExtensionAppShimHandler::OnExtensionEnabled( | |
376 Host* host, | |
377 Profile* profile, | |
378 const std::vector<base::FilePath>& files) { | |
379 const extensions::Extension* extension = | |
380 delegate_->GetAppExtension(profile, host->GetAppId()); | |
381 if (!extension) { | |
382 host->OnAppLaunchComplete(APP_SHIM_LAUNCH_APP_NOT_FOUND); | |
383 return; | |
384 } | |
385 | |
386 delegate_->LaunchApp(profile, extension, files); | |
387 } | |
388 | |
389 | |
320 void ExtensionAppShimHandler::OnShimClose(Host* host) { | 390 void ExtensionAppShimHandler::OnShimClose(Host* host) { |
321 // This might be called when shutting down. Don't try to look up the profile | 391 // This might be called when shutting down. Don't try to look up the profile |
322 // since profile_manager might not be around. | 392 // since profile_manager might not be around. |
323 for (HostMap::iterator it = hosts_.begin(); it != hosts_.end(); ) { | 393 for (HostMap::iterator it = hosts_.begin(); it != hosts_.end(); ) { |
324 HostMap::iterator current = it++; | 394 HostMap::iterator current = it++; |
325 if (current->second == host) | 395 if (current->second == host) |
326 hosts_.erase(current); | 396 hosts_.erase(current); |
327 } | 397 } |
328 } | 398 } |
329 | 399 |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
441 if (hosts_.empty()) | 511 if (hosts_.empty()) |
442 delegate_->MaybeTerminate(); | 512 delegate_->MaybeTerminate(); |
443 } | 513 } |
444 | 514 |
445 void ExtensionAppShimHandler::OnAppStop(Profile* profile, | 515 void ExtensionAppShimHandler::OnAppStop(Profile* profile, |
446 const std::string& app_id) {} | 516 const std::string& app_id) {} |
447 | 517 |
448 void ExtensionAppShimHandler::OnChromeTerminating() {} | 518 void ExtensionAppShimHandler::OnChromeTerminating() {} |
449 | 519 |
450 } // namespace apps | 520 } // namespace apps |
OLD | NEW |