Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Side by Side Diff: apps/app_shim/extension_app_shim_handler_mac.cc

Issue 17481002: Restructure ExtensionAppShimHandler testing. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 ProfileManager* profile_manager = g_browser_process->profile_manager(); 45 ProfileManager* profile_manager = g_browser_process->profile_manager();
61 base::FilePath full_path = profile_manager->user_data_dir().Append(path); 46 base::FilePath full_path = profile_manager->user_data_dir().Append(path);
tapted 2013/06/21 06:07:02 some screwy stuff here from a rebase
jackhou1 2013/06/21 06:53:57 Oh yeah, I rebased to pick up http://crrev.com/175
tapted 2013/06/21 08:02:32 Ahh - I see, the rebase was not in a separate CL (
62 return profile_manager->GetProfile(full_path); 47 return profile_manager->GetProfile(full_path);
63 } 48 }
64 49
50 ShellWindowList ExtensionAppShimHandler::Delegate::GetWindows(
51 Profile* profile,
52 const std::string& extension_id) {
53 return extensions::ShellWindowRegistry::Get(profile)->
54 GetShellWindowsForApp(extension_id);
55 }
56
57 const extensions::Extension*
58 ExtensionAppShimHandler::Delegate::GetAppExtension(
59 Profile* profile,
60 const std::string& extension_id) {
61 ExtensionService* extension_service =
62 extensions::ExtensionSystem::Get(profile)->extension_service();
63 DCHECK(extension_service);
64 const extensions::Extension* extension =
65 extension_service->GetExtensionById(extension_id, false);
66 return extension && extension->is_platform_app() ? extension : NULL;
67 }
68
69 void ExtensionAppShimHandler::Delegate::LaunchApp(
70 Profile* profile,
71 const extensions::Extension* extension) {
72 chrome::OpenApplication(chrome::AppLaunchParams(
tapted 2013/06/21 06:07:02 nit: might be marginally nicer to linebreak on the
jackhou1 2013/06/21 06:53:57 Done.
73 profile, extension, NEW_FOREGROUND_TAB));
74 }
75
76 void ExtensionAppShimHandler::Delegate::LaunchShim(
77 Profile* profile,
78 const extensions::Extension* extension) {
79 web_app::MaybeLaunchShortcut(
80 web_app::ShortcutInfoForExtensionAndProfile(extension, profile));
81 }
82
65 ExtensionAppShimHandler::ExtensionAppShimHandler() 83 ExtensionAppShimHandler::ExtensionAppShimHandler()
66 : profile_manager_facade_(new ProfileManagerFacade) { 84 : delegate_(new Delegate) {
67 // This is instantiated in BrowserProcessImpl::PreMainMessageLoopRun with 85 // This is instantiated in BrowserProcessImpl::PreMainMessageLoopRun with
68 // AppShimHostManager. Since PROFILE_CREATED is not fired until 86 // AppShimHostManager. Since PROFILE_CREATED is not fired until
69 // ProfileManager::GetLastUsedProfile/GetLastOpenedProfiles, this should catch 87 // ProfileManager::GetLastUsedProfile/GetLastOpenedProfiles, this should catch
70 // notifications for all profiles. 88 // notifications for all profiles.
71 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, 89 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED,
72 content::NotificationService::AllBrowserContextsAndSources()); 90 content::NotificationService::AllBrowserContextsAndSources());
73 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, 91 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
74 content::NotificationService::AllBrowserContextsAndSources()); 92 content::NotificationService::AllBrowserContextsAndSources());
75 } 93 }
76 94
77 ExtensionAppShimHandler::~ExtensionAppShimHandler() {} 95 ExtensionAppShimHandler::~ExtensionAppShimHandler() {}
78 96
79 bool ExtensionAppShimHandler::OnShimLaunch(Host* host, 97 bool ExtensionAppShimHandler::OnShimLaunch(Host* host,
80 AppShimLaunchType launch_type) { 98 AppShimLaunchType launch_type) {
81 const base::FilePath& profile_path = host->GetProfilePath(); 99 const base::FilePath& profile_path = host->GetProfilePath();
82 DCHECK(!profile_path.empty()); 100 DCHECK(!profile_path.empty());
83 101
84 if (!profile_manager_facade_->ProfileExistsForPath(profile_path)) { 102 if (!delegate_->ProfileExistsForPath(profile_path)) {
85 // User may have deleted the profile this shim was originally created for. 103 // User may have deleted the profile this shim was originally created for.
86 // TODO(jackhou): Add some UI for this case and remove the LOG. 104 // TODO(jackhou): Add some UI for this case and remove the LOG.
87 LOG(ERROR) << "Requested directory is not a known profile '" 105 LOG(ERROR) << "Requested directory is not a known profile '"
88 << profile_path.value() << "'."; 106 << profile_path.value() << "'.";
89 return false; 107 return false;
90 } 108 }
91 109
92 Profile* profile = profile_manager_facade_->ProfileForPath(profile_path); 110 Profile* profile = delegate_->ProfileForPath(profile_path);
93 111
94 const std::string& app_id = host->GetAppId(); 112 const std::string& app_id = host->GetAppId();
95 if (!extensions::Extension::IdIsValid(app_id)) { 113 if (!extensions::Extension::IdIsValid(app_id)) {
96 LOG(ERROR) << "Bad app ID from app shim launch message."; 114 LOG(ERROR) << "Bad app ID from app shim launch message.";
97 return false; 115 return false;
98 } 116 }
99 117
100 // TODO(jackhou): Add some UI for this case and remove the LOG. 118 // TODO(jackhou): Add some UI for this case and remove the LOG.
101 if (!LaunchApp(profile, app_id, launch_type)) 119 const extensions::Extension* extension =
120 delegate_->GetAppExtension(profile, app_id);
121 if (!extension) {
122 LOG(ERROR) << "Attempted to launch nonexistent app with id '"
123 << app_id << "'.";
102 return false; 124 return false;
125 }
126
127 // If the shim was launched in response to a window appearing, but the window
128 // is closed by the time the shim process launched, return false to close the
129 // shim.
130 if (launch_type == APP_SHIM_LAUNCH_REGISTER_ONLY &&
131 delegate_->GetWindows(profile, app_id).empty()) {
132 return false;
133 }
134
135 // TODO(jeremya): Handle the case that launching the app fails. Probably we
136 // need to watch for 'app successfully launched' or at least 'background page
137 // exists/was created' and time out with failure if we don't see that sign of
138 // life within a certain window.
139 if (launch_type == APP_SHIM_LAUNCH_NORMAL) {
tapted 2013/06/21 06:07:02 nit: doesn't need curlies
jackhou1 2013/06/21 06:53:57 Done.
140 delegate_->LaunchApp(profile, extension);
141 }
103 142
104 // The first host to claim this (profile, app_id) becomes the main host. 143 // The first host to claim this (profile, app_id) becomes the main host.
105 // For any others, focus the app and return false. 144 // For any others, focus the app and return false.
106 if (!hosts_.insert(make_pair(make_pair(profile, app_id), host)).second) { 145 if (!hosts_.insert(make_pair(make_pair(profile, app_id), host)).second) {
107 OnShimFocus(host); 146 OnShimFocus(host);
108 return false; 147 return false;
109 } 148 }
110 149
111 return true; 150 return true;
112 } 151 }
113 152
114 void ExtensionAppShimHandler::OnShimClose(Host* host) { 153 void ExtensionAppShimHandler::OnShimClose(Host* host) {
115 DCHECK(profile_manager_facade_->ProfileExistsForPath( 154 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath()));
116 host->GetProfilePath())); 155 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath());
117 Profile* profile =
118 profile_manager_facade_->ProfileForPath(host->GetProfilePath());
119 156
120 HostMap::iterator it = hosts_.find(make_pair(profile, host->GetAppId())); 157 HostMap::iterator it = hosts_.find(make_pair(profile, host->GetAppId()));
121 // Any hosts other than the main host will still call OnShimClose, so ignore 158 // Any hosts other than the main host will still call OnShimClose, so ignore
122 // them. 159 // them.
123 if (it != hosts_.end() && it->second == host) 160 if (it != hosts_.end() && it->second == host)
124 hosts_.erase(it); 161 hosts_.erase(it);
125 } 162 }
126 163
127 void ExtensionAppShimHandler::OnShimFocus(Host* host) { 164 void ExtensionAppShimHandler::OnShimFocus(Host* host) {
128 DCHECK(profile_manager_facade_->ProfileExistsForPath( 165 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath()));
129 host->GetProfilePath())); 166 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath());
130 Profile* profile =
131 profile_manager_facade_->ProfileForPath(host->GetProfilePath());
132 167
133 const ShellWindowList windows = GetWindows(profile, host->GetAppId()); 168 const ShellWindowList windows =
169 delegate_->GetWindows(profile, host->GetAppId());
134 std::set<gfx::NativeWindow> native_windows; 170 std::set<gfx::NativeWindow> native_windows;
135 for (ShellWindowList::const_iterator it = windows.begin(); 171 for (ShellWindowList::const_iterator it = windows.begin();
136 it != windows.end(); ++it) { 172 it != windows.end(); ++it) {
137 native_windows.insert((*it)->GetNativeWindow()); 173 native_windows.insert((*it)->GetNativeWindow());
138 } 174 }
139 ui::FocusWindowSet(native_windows); 175 ui::FocusWindowSet(native_windows);
140 } 176 }
141 177
142 void ExtensionAppShimHandler::OnShimQuit(Host* host) { 178 void ExtensionAppShimHandler::OnShimQuit(Host* host) {
143 DCHECK(profile_manager_facade_->ProfileExistsForPath( 179 DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath()));
144 host->GetProfilePath())); 180 Profile* profile = delegate_->ProfileForPath(host->GetProfilePath());
145 Profile* profile =
146 profile_manager_facade_->ProfileForPath(host->GetProfilePath());
147 181
148 const ShellWindowList windows = GetWindows(profile, host->GetAppId()); 182 const ShellWindowList windows =
183 delegate_->GetWindows(profile, host->GetAppId());
149 for (extensions::ShellWindowRegistry::const_iterator it = windows.begin(); 184 for (extensions::ShellWindowRegistry::const_iterator it = windows.begin();
150 it != windows.end(); ++it) { 185 it != windows.end(); ++it) {
151 (*it)->GetBaseWindow()->Close(); 186 (*it)->GetBaseWindow()->Close();
152 } 187 }
153 } 188 }
154 189
155 void ExtensionAppShimHandler::set_profile_manager_facade( 190 void ExtensionAppShimHandler::set_delegate(Delegate* delegate) {
156 ProfileManagerFacade* profile_manager_facade) { 191 delegate_.reset(delegate);
157 profile_manager_facade_.reset(profile_manager_facade);
158 }
159
160 bool ExtensionAppShimHandler::LaunchApp(Profile* profile,
161 const std::string& app_id,
162 AppShimLaunchType launch_type) {
163 const extensions::Extension* extension = GetExtension(profile, app_id);
164 if (!extension) {
165 LOG(ERROR) << "Attempted to launch nonexistent app with id '"
166 << app_id << "'.";
167 return false;
168 }
169
170 if (launch_type == APP_SHIM_LAUNCH_REGISTER_ONLY)
171 return !GetWindows(profile, app_id).empty();
172
173 // TODO(jeremya): Handle the case that launching the app fails. Probably we
174 // need to watch for 'app successfully launched' or at least 'background page
175 // exists/was created' and time out with failure if we don't see that sign of
176 // life within a certain window.
177 chrome::OpenApplication(chrome::AppLaunchParams(
178 profile, extension, NEW_FOREGROUND_TAB));
179 return true;
180 } 192 }
181 193
182 void ExtensionAppShimHandler::Observe( 194 void ExtensionAppShimHandler::Observe(
183 int type, 195 int type,
184 const content::NotificationSource& source, 196 const content::NotificationSource& source,
185 const content::NotificationDetails& details) { 197 const content::NotificationDetails& details) {
186 Profile* profile = content::Source<Profile>(source).ptr(); 198 Profile* profile = content::Source<Profile>(source).ptr();
187 if (profile->IsOffTheRecord()) 199 if (profile->IsOffTheRecord())
188 return; 200 return;
189 201
(...skipping 16 matching lines...) Expand all
206 NOTREACHED(); // Unexpected notification. 218 NOTREACHED(); // Unexpected notification.
207 break; 219 break;
208 } 220 }
209 } 221 }
210 222
211 void ExtensionAppShimHandler::OnAppStart(Profile* profile, 223 void ExtensionAppShimHandler::OnAppStart(Profile* profile,
212 const std::string& app_id) {} 224 const std::string& app_id) {}
213 225
214 void ExtensionAppShimHandler::OnAppActivated(Profile* profile, 226 void ExtensionAppShimHandler::OnAppActivated(Profile* profile,
215 const std::string& app_id) { 227 const std::string& app_id) {
216 const extensions::Extension* extension = GetExtension(profile, app_id); 228 const extensions::Extension* extension =
217 if (!extension || !extension->is_platform_app()) 229 delegate_->GetAppExtension(profile, app_id);
230 if (!extension)
218 return; 231 return;
219 232
220 if (hosts_.count(make_pair(profile, extension->id()))) 233 if (hosts_.count(make_pair(profile, app_id)))
221 return; 234 return;
222 235
223 web_app::MaybeLaunchShortcut( 236 delegate_->LaunchShim(profile, extension);
224 web_app::ShortcutInfoForExtensionAndProfile(extension, profile));
225 } 237 }
226 238
227 void ExtensionAppShimHandler::OnAppDeactivated(Profile* profile, 239 void ExtensionAppShimHandler::OnAppDeactivated(Profile* profile,
228 const std::string& app_id) { 240 const std::string& app_id) {
229 HostMap::const_iterator it = hosts_.find(make_pair(profile, app_id)); 241 HostMap::const_iterator it = hosts_.find(make_pair(profile, app_id));
230 if (it != hosts_.end()) 242 if (it != hosts_.end())
231 it->second->OnAppClosed(); 243 it->second->OnAppClosed();
232 } 244 }
233 245
234 void ExtensionAppShimHandler::OnAppStop(Profile* profile, 246 void ExtensionAppShimHandler::OnAppStop(Profile* profile,
235 const std::string& app_id) {} 247 const std::string& app_id) {}
236 248
237 void ExtensionAppShimHandler::OnChromeTerminating() {} 249 void ExtensionAppShimHandler::OnChromeTerminating() {}
238 250
239 } // namespace apps 251 } // namespace apps
OLDNEW
« no previous file with comments | « apps/app_shim/extension_app_shim_handler_mac.h ('k') | apps/app_shim/extension_app_shim_handler_mac_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698