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

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

Issue 15269003: Refactor extension handling code from AppShimHost into ExtensionAppShimHandler. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add default handler to AppShimHandler. Fix test. Created 7 years, 7 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/app_shim_host_mac.h" 5 #include "apps/app_shim/app_shim_host_mac.h"
6 6
7 #include "apps/app_shim/app_shim_handler_mac.h" 7 #include "apps/app_shim/app_shim_handler_mac.h"
8 #include "apps/app_shim/app_shim_messages.h" 8 #include "apps/app_shim/app_shim_messages.h"
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/files/file_path.h" 10 #include "base/files/file_path.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "chrome/browser/browser_process.h" 12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/extensions/extension_host.h" 13 #include "chrome/browser/extensions/extension_host.h"
14 #include "chrome/browser/extensions/extension_service.h" 14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/extensions/extension_system.h" 15 #include "chrome/browser/extensions/extension_system.h"
16 #include "chrome/browser/extensions/shell_window_registry.h" 16 #include "chrome/browser/extensions/shell_window_registry.h"
tapted 2013/05/21 06:15:37 A lot of these #includes are probably unused now.
jackhou1 2013/05/22 23:54:44 Done.
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/shell_window.h" 19 #include "chrome/browser/ui/extensions/shell_window.h"
20 #include "chrome/common/extensions/extension_constants.h" 20 #include "chrome/common/extensions/extension_constants.h"
21 #include "ipc/ipc_channel_proxy.h" 21 #include "ipc/ipc_channel_proxy.h"
22 #include "ui/base/cocoa/focus_window_set.h" 22 #include "ui/base/cocoa/focus_window_set.h"
23 23
24 AppShimHost::AppShimHost() 24 AppShimHost::AppShimHost()
25 : channel_(NULL), profile_(NULL) { 25 : channel_(NULL), profile_(NULL) {
26 } 26 }
27 27
28 AppShimHost::~AppShimHost() { 28 AppShimHost::~AppShimHost() {
29 DCHECK(CalledOnValidThread()); 29 DCHECK(CalledOnValidThread());
30 apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_); 30 apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
31 if (handler) 31 if (handler)
32 handler->OnShimClose(this); 32 handler->OnShimClose(this);
33 } 33 }
34 34
35 void AppShimHost::ServeChannel(const IPC::ChannelHandle& handle) { 35 void AppShimHost::ServeChannel(const IPC::ChannelHandle& handle) {
36 DCHECK(CalledOnValidThread()); 36 DCHECK(CalledOnValidThread());
37 DCHECK(!channel_.get()); 37 DCHECK(!channel_.get());
38 channel_.reset(new IPC::ChannelProxy(handle, IPC::Channel::MODE_SERVER, this, 38 channel_.reset(new IPC::ChannelProxy(handle, IPC::Channel::MODE_SERVER, this,
39 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))); 39 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)));
40 } 40 }
41 41
42 const std::string& AppShimHost::app_id() const {
43 return app_id_;
44 }
45
46 Profile* AppShimHost::profile() const {
47 return profile_;
48 }
49
42 bool AppShimHost::OnMessageReceived(const IPC::Message& message) { 50 bool AppShimHost::OnMessageReceived(const IPC::Message& message) {
43 DCHECK(CalledOnValidThread()); 51 DCHECK(CalledOnValidThread());
44 bool handled = true; 52 bool handled = true;
45 IPC_BEGIN_MESSAGE_MAP(AppShimHost, message) 53 IPC_BEGIN_MESSAGE_MAP(AppShimHost, message)
46 IPC_MESSAGE_HANDLER(AppShimHostMsg_LaunchApp, OnLaunchApp) 54 IPC_MESSAGE_HANDLER(AppShimHostMsg_LaunchApp, OnLaunchApp)
47 IPC_MESSAGE_HANDLER(AppShimHostMsg_FocusApp, OnFocus) 55 IPC_MESSAGE_HANDLER(AppShimHostMsg_FocusApp, OnFocus)
48 IPC_MESSAGE_UNHANDLED(handled = false) 56 IPC_MESSAGE_UNHANDLED(handled = false)
49 IPC_END_MESSAGE_MAP() 57 IPC_END_MESSAGE_MAP()
50 58
51 return handled; 59 return handled;
52 } 60 }
53 61
54 void AppShimHost::OnChannelError() { 62 void AppShimHost::OnChannelError() {
55 Close(); 63 Close();
56 } 64 }
57 65
58 bool AppShimHost::Send(IPC::Message* message) { 66 bool AppShimHost::Send(IPC::Message* message) {
59 DCHECK(channel_.get()); 67 DCHECK(channel_.get());
60 return channel_->Send(message); 68 return channel_->Send(message);
61 } 69 }
62 70
63 void AppShimHost::OnLaunchApp(std::string profile_dir, std::string app_id) { 71 void AppShimHost::OnLaunchApp(std::string profile_dir, std::string app_id) {
64 DCHECK(CalledOnValidThread()); 72 DCHECK(CalledOnValidThread());
73 if (profile_) {
tapted 2013/05/21 06:15:37 Maybe DCHECK(!profile) as well? There would need t
jackhou1 2013/05/22 23:54:44 Done.
74 // Only one app launch message per channel.
75 Send(new AppShimMsg_LaunchApp_Done(false));
76 return;
77 }
78 profile_ = FetchProfileForDirectory(profile_dir);
tapted 2013/05/21 06:15:37 nit: blank line before, for early return
jackhou1 2013/05/22 23:54:44 Done.
65 app_id_ = app_id; 79 app_id_ = app_id;
66 apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_); 80 apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
67 bool success = 81 bool success = handler && handler->OnShimLaunch(this);
68 handler ? handler->OnShimLaunch(this) : LaunchAppImpl(profile_dir);
69 Send(new AppShimMsg_LaunchApp_Done(success)); 82 Send(new AppShimMsg_LaunchApp_Done(success));
70 } 83 }
71 84
72 void AppShimHost::OnFocus() { 85 void AppShimHost::OnFocus() {
73 DCHECK(CalledOnValidThread()); 86 DCHECK(CalledOnValidThread());
74 apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_); 87 apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
75 if (handler) { 88 if (handler)
76 handler->OnShimFocus(this); 89 handler->OnShimFocus(this);
77 return;
78 }
79
80 if (!profile_)
81 return;
82 extensions::ShellWindowRegistry* registry =
83 extensions::ShellWindowRegistry::Get(profile_);
84 const std::set<ShellWindow*> windows =
85 registry->GetShellWindowsForApp(app_id_);
86 std::set<gfx::NativeWindow> native_windows;
87 for (std::set<ShellWindow*>::const_iterator i = windows.begin();
88 i != windows.end();
89 ++i) {
90 native_windows.insert((*i)->GetNativeWindow());
91 }
92 ui::FocusWindowSet(native_windows);
93 }
94
95 bool AppShimHost::LaunchAppImpl(const std::string& profile_dir) {
96 DCHECK(CalledOnValidThread());
97 if (profile_) {
98 // Only one app launch message per channel.
99 return false;
100 }
101 if (!extensions::Extension::IdIsValid(app_id_)) {
102 LOG(ERROR) << "Bad app ID from app shim launch message.";
103 return false;
104 }
105 Profile* profile = FetchProfileForDirectory(profile_dir);
106 if (!profile)
107 return false;
108
109 if (!LaunchApp(profile))
110 return false;
111
112 profile_ = profile;
113 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
114 content::Source<Profile>(profile_));
115 return true;
116 } 90 }
117 91
118 Profile* AppShimHost::FetchProfileForDirectory(const std::string& profile_dir) { 92 Profile* AppShimHost::FetchProfileForDirectory(const std::string& profile_dir) {
119 ProfileManager* profileManager = g_browser_process->profile_manager(); 93 ProfileManager* profileManager = g_browser_process->profile_manager();
120 // Even though the name of this function is "unsafe", there's no security 94 // Even though the name of this function is "unsafe", there's no security
121 // issue here -- the check for the profile name in the profile info cache 95 // issue here -- the check for the profile name in the profile info cache
122 // ensures that we never access any directory that isn't a known profile. 96 // ensures that we never access any directory that isn't a known profile.
123 base::FilePath path = base::FilePath::FromUTF8Unsafe(profile_dir); 97 base::FilePath path = base::FilePath::FromUTF8Unsafe(profile_dir);
124 path = profileManager->user_data_dir().Append(path); 98 path = profileManager->user_data_dir().Append(path);
125 ProfileInfoCache& cache = profileManager->GetProfileInfoCache(); 99 ProfileInfoCache& cache = profileManager->GetProfileInfoCache();
126 // This ensures that the given profile path is acutally a profile that we 100 // This ensures that the given profile path is acutally a profile that we
127 // already know about. 101 // already know about.
128 if (cache.GetIndexOfProfileWithPath(path) == std::string::npos) { 102 if (cache.GetIndexOfProfileWithPath(path) == std::string::npos) {
129 LOG(ERROR) << "Requested directory is not a known profile '" 103 LOG(ERROR) << "Requested directory is not a known profile '"
130 << profile_dir << "'."; 104 << profile_dir << "'.";
131 return NULL; 105 return NULL;
132 } 106 }
133 Profile* profile = profileManager->GetProfile(path); 107 Profile* profile = profileManager->GetProfile(path);
134 if (!profile) { 108 if (!profile) {
135 LOG(ERROR) << "Couldn't get profile for directory '" << profile_dir << "'."; 109 LOG(ERROR) << "Couldn't get profile for directory '" << profile_dir << "'.";
136 return NULL; 110 return NULL;
137 } 111 }
138 return profile; 112 return profile;
139 } 113 }
140 114
141 bool AppShimHost::LaunchApp(Profile* profile) {
142 extensions::ExtensionSystem* extension_system =
143 extensions::ExtensionSystem::Get(profile);
144 ExtensionServiceInterface* extension_service =
145 extension_system->extension_service();
146 const extensions::Extension* extension =
147 extension_service->GetExtensionById(
148 app_id_, false);
149 if (!extension) {
150 LOG(ERROR) << "Attempted to launch nonexistent app with id '"
151 << app_id_ << "'.";
152 return false;
153 }
154 // TODO(jeremya): Handle the case that launching the app fails. Probably we
155 // need to watch for 'app successfully launched' or at least 'background page
156 // exists/was created' and time out with failure if we don't see that sign of
157 // life within a certain window.
158 chrome::AppLaunchParams params(profile,
159 extension,
160 extension_misc::LAUNCH_NONE,
161 NEW_WINDOW);
162 chrome::OpenApplication(params);
163 return true;
164 }
165
166 void AppShimHost::Observe(int type,
167 const content::NotificationSource& source,
168 const content::NotificationDetails& details) {
169 DCHECK(CalledOnValidThread());
170 DCHECK(content::Source<Profile>(source).ptr() == profile_);
171 switch (type) {
172 case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: {
173 extensions::ExtensionHost* extension_host =
174 content::Details<extensions::ExtensionHost>(details).ptr();
175 if (app_id_ == extension_host->extension_id())
176 Close();
177 break;
178 }
179 default:
180 NOTREACHED() << "Unexpected notification sent.";
181 break;
182 }
183 }
184
185 void AppShimHost::OnAppClosed() { 115 void AppShimHost::OnAppClosed() {
186 Close(); 116 Close();
187 } 117 }
188 118
189 void AppShimHost::Close() { 119 void AppShimHost::Close() {
190 DCHECK(CalledOnValidThread()); 120 DCHECK(CalledOnValidThread());
191 delete this; 121 delete this;
192 } 122 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698