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

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: Change to map of Hosts (no ObserverList). Improve 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"
14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/extensions/extension_system.h"
16 #include "chrome/browser/extensions/shell_window_registry.h"
17 #include "chrome/browser/profiles/profile_manager.h" 13 #include "chrome/browser/profiles/profile_manager.h"
18 #include "chrome/browser/ui/extensions/application_launch.h" 14 #include "content/public/browser/browser_thread.h"
19 #include "chrome/browser/ui/extensions/shell_window.h"
20 #include "chrome/common/extensions/extension_constants.h"
21 #include "ipc/ipc_channel_proxy.h" 15 #include "ipc/ipc_channel_proxy.h"
22 #include "ui/base/cocoa/focus_window_set.h"
23 16
24 AppShimHost::AppShimHost() 17 AppShimHost::AppShimHost()
25 : channel_(NULL), profile_(NULL) { 18 : channel_(NULL), profile_(NULL) {
26 } 19 }
27 20
28 AppShimHost::~AppShimHost() { 21 AppShimHost::~AppShimHost() {
29 DCHECK(CalledOnValidThread()); 22 DCHECK(CalledOnValidThread());
30 apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_); 23 apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
31 if (handler) 24 if (handler)
32 handler->OnShimClose(this); 25 handler->OnShimClose(this);
33 } 26 }
34 27
35 void AppShimHost::ServeChannel(const IPC::ChannelHandle& handle) { 28 void AppShimHost::ServeChannel(const IPC::ChannelHandle& handle) {
36 DCHECK(CalledOnValidThread()); 29 DCHECK(CalledOnValidThread());
37 DCHECK(!channel_.get()); 30 DCHECK(!channel_.get());
38 channel_.reset(new IPC::ChannelProxy(handle, IPC::Channel::MODE_SERVER, this, 31 channel_.reset(new IPC::ChannelProxy(handle, IPC::Channel::MODE_SERVER, this,
39 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))); 32 content::BrowserThread::GetMessageLoopProxyForThread(
33 content::BrowserThread::IO)));
34 }
35
36 Profile* AppShimHost::GetProfile() const {
37 return profile_;
38 }
39
40 std::string AppShimHost::GetAppId() const {
41 return app_id_;
40 } 42 }
41 43
42 bool AppShimHost::OnMessageReceived(const IPC::Message& message) { 44 bool AppShimHost::OnMessageReceived(const IPC::Message& message) {
43 DCHECK(CalledOnValidThread()); 45 DCHECK(CalledOnValidThread());
44 bool handled = true; 46 bool handled = true;
45 IPC_BEGIN_MESSAGE_MAP(AppShimHost, message) 47 IPC_BEGIN_MESSAGE_MAP(AppShimHost, message)
46 IPC_MESSAGE_HANDLER(AppShimHostMsg_LaunchApp, OnLaunchApp) 48 IPC_MESSAGE_HANDLER(AppShimHostMsg_LaunchApp, OnLaunchApp)
47 IPC_MESSAGE_HANDLER(AppShimHostMsg_FocusApp, OnFocus) 49 IPC_MESSAGE_HANDLER(AppShimHostMsg_FocusApp, OnFocus)
48 IPC_MESSAGE_UNHANDLED(handled = false) 50 IPC_MESSAGE_UNHANDLED(handled = false)
49 IPC_END_MESSAGE_MAP() 51 IPC_END_MESSAGE_MAP()
50 52
51 return handled; 53 return handled;
52 } 54 }
53 55
54 void AppShimHost::OnChannelError() { 56 void AppShimHost::OnChannelError() {
55 Close(); 57 Close();
56 } 58 }
57 59
58 bool AppShimHost::Send(IPC::Message* message) { 60 bool AppShimHost::Send(IPC::Message* message) {
59 DCHECK(channel_.get()); 61 DCHECK(channel_.get());
60 return channel_->Send(message); 62 return channel_->Send(message);
61 } 63 }
62 64
63 void AppShimHost::OnLaunchApp(std::string profile_dir, std::string app_id) { 65 void AppShimHost::OnLaunchApp(std::string profile_dir, std::string app_id) {
64 DCHECK(CalledOnValidThread()); 66 DCHECK(CalledOnValidThread());
67 DCHECK(!profile_);
68 if (profile_) {
69 // Only one app launch message per channel.
70 Send(new AppShimMsg_LaunchApp_Done(false));
71 return;
72 }
73
74 profile_ = FetchProfileForDirectory(profile_dir);
65 app_id_ = app_id; 75 app_id_ = app_id;
66 apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_); 76 apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
67 bool success = 77 bool success = handler && handler->OnShimLaunch(this);
68 handler ? handler->OnShimLaunch(this) : LaunchAppImpl(profile_dir);
69 Send(new AppShimMsg_LaunchApp_Done(success)); 78 Send(new AppShimMsg_LaunchApp_Done(success));
70 } 79 }
71 80
72 void AppShimHost::OnFocus() { 81 void AppShimHost::OnFocus() {
73 DCHECK(CalledOnValidThread()); 82 DCHECK(CalledOnValidThread());
74 apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_); 83 apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
75 if (handler) { 84 if (handler)
76 handler->OnShimFocus(this); 85 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 } 86 }
117 87
118 Profile* AppShimHost::FetchProfileForDirectory(const std::string& profile_dir) { 88 Profile* AppShimHost::FetchProfileForDirectory(const std::string& profile_dir) {
119 ProfileManager* profileManager = g_browser_process->profile_manager(); 89 ProfileManager* profileManager = g_browser_process->profile_manager();
120 // Even though the name of this function is "unsafe", there's no security 90 // 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 91 // 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. 92 // ensures that we never access any directory that isn't a known profile.
123 base::FilePath path = base::FilePath::FromUTF8Unsafe(profile_dir); 93 base::FilePath path = base::FilePath::FromUTF8Unsafe(profile_dir);
124 path = profileManager->user_data_dir().Append(path); 94 path = profileManager->user_data_dir().Append(path);
125 ProfileInfoCache& cache = profileManager->GetProfileInfoCache(); 95 ProfileInfoCache& cache = profileManager->GetProfileInfoCache();
126 // This ensures that the given profile path is acutally a profile that we 96 // This ensures that the given profile path is acutally a profile that we
127 // already know about. 97 // already know about.
128 if (cache.GetIndexOfProfileWithPath(path) == std::string::npos) { 98 if (cache.GetIndexOfProfileWithPath(path) == std::string::npos) {
129 LOG(ERROR) << "Requested directory is not a known profile '" 99 LOG(ERROR) << "Requested directory is not a known profile '"
130 << profile_dir << "'."; 100 << profile_dir << "'.";
131 return NULL; 101 return NULL;
132 } 102 }
133 Profile* profile = profileManager->GetProfile(path); 103 Profile* profile = profileManager->GetProfile(path);
134 if (!profile) { 104 if (!profile) {
135 LOG(ERROR) << "Couldn't get profile for directory '" << profile_dir << "'."; 105 LOG(ERROR) << "Couldn't get profile for directory '" << profile_dir << "'.";
136 return NULL; 106 return NULL;
137 } 107 }
138 return profile; 108 return profile;
139 } 109 }
140 110
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() { 111 void AppShimHost::OnAppClosed() {
186 Close(); 112 Close();
187 } 113 }
188 114
189 void AppShimHost::Close() { 115 void AppShimHost::Close() {
190 DCHECK(CalledOnValidThread()); 116 DCHECK(CalledOnValidThread());
191 delete this; 117 delete this;
192 } 118 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698