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

Side by Side Diff: chrome/browser/extensions/platform_app_launcher.cc

Issue 10332071: Pass command line arguments onto platform apps which provide the right intent. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Compile fixed, postResult added Created 8 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
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/extensions/platform_app_launcher.h"
6
7 #include "base/command_line.h"
8 #include "base/file_path.h"
9 #include "base/file_util.h"
10 #include "base/logging.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/string_util.h"
13 #include "base/utf_string_conversions.h"
14 #include "chrome/browser/extensions/api/app/app_api.h"
15 #include "chrome/browser/extensions/extension_host.h"
16 #include "chrome/browser/extensions/extension_process_manager.h"
17 #include "chrome/browser/extensions/extension_system.h"
18 #include "chrome/browser/extensions/lazy_background_task_queue.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/common/extensions/extension.h"
21 #include "chrome/common/extensions/extension_messages.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/child_process_security_policy.h"
24 #include "content/public/browser/render_process_host.h"
25 #include "net/base/mime_util.h"
26 #include "net/base/net_util.h"
27 #include "webkit/fileapi/isolated_context.h"
28 #include "webkit/glue/web_intent_service_data.h"
29
30 using content::BrowserThread;
31
32 namespace {
33
34 const char kViewIntent[] = "http://webintents.org/view";
Mihai Parparita -not on Chrome 2012/05/18 04:26:04 Rather than having this as a a constant here and D
benwells 2012/05/18 04:56:55 How is it error-prone? Do you mean if the code use
benwells 2012/05/22 13:15:03 After talking to Mihai will leave as is.
35
36 class PlatformAppLauncher
37 : public base::RefCountedThreadSafe<PlatformAppLauncher> {
38 public:
39 PlatformAppLauncher(Profile* profile,
40 const Extension* extension,
41 const CommandLine* command_line)
42 : profile_(profile),
43 extension_(extension),
44 command_line_(command_line) {}
45
46 void Launch() {
47 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
48 if (!command_line_ || !command_line_->GetArgs().size()) {
49 LaunchWithNoLaunchData();
50 return;
51 }
52
53 FilePath file_path(command_line_->GetArgs()[0]);
54 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(
55 &PlatformAppLauncher::GetMimeTypeAndLaunch, this, file_path));
56 }
57
58 private:
59 void LaunchWithNoLaunchData() {
60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
61 extensions::AppEventRouter::DispatchOnLaunchedEvent(profile_, extension_);
62 }
63
64 void GetMimeTypeAndLaunch(const FilePath& file_path) {
65 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
66
67 // If the file doesn't exist, or is a directory, launch with no launch data.
68 if (!file_util::PathExists(file_path) ||
69 file_util::DirectoryExists(file_path)) {
70 LOG(WARNING) << "No file exists with path " << file_path.value();
71 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
72 &PlatformAppLauncher::LaunchWithNoLaunchData, this));
73 return;
74 }
75
76 std::string mime_type;
77 // If we cannot obtain the MIME type, launch with no launch data.
78 if (!net::GetMimeTypeFromFile(file_path, &mime_type)) {
79 LOG(WARNING) << "Could not obtain MIME type for " << file_path.value();
80 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
81 &PlatformAppLauncher::LaunchWithNoLaunchData, this));
82 return;
83 }
84
85 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
86 &PlatformAppLauncher::LaunchWithMimeTypeAndPath, this, file_path,
87 mime_type));
88 }
89
90 void LaunchWithMimeTypeAndPath(const FilePath& file_path,
91 const std::string& mime_type) {
92 // Find the intent service from the platform app for the file being opened.
93 webkit_glue::WebIntentServiceData service;
94 bool found_service = false;
95
96 std::vector<webkit_glue::WebIntentServiceData> services =
97 extension_->intents_services();
98 for (size_t i = 0; i < services.size(); i++) {
99 std::string service_type_ascii = UTF16ToASCII(services[i].type);
100 if (services[i].action == ASCIIToUTF16(kViewIntent) &&
101 net::MatchesMimeType(service_type_ascii, mime_type)) {
102 service = services[i];
103 found_service = true;
Mihai Parparita -not on Chrome 2012/05/18 04:26:04 Add a break here.
benwells 2012/05/22 13:15:03 Done.
104 }
105 }
106
107 // If this app doesn't have an intent that supports the file, launch with
108 // no launch data.
109 if (!found_service) {
110 LOG(WARNING) << "Extension does not provide a valid intent for "
111 << file_path.value();
112 LaunchWithNoLaunchData();
113 return;
114 }
115
116 // We need to grant access to the file for the process associated with the
117 // extension. To do this we need the ExtensionHost, so we try and get it.
118 ExtensionProcessManager* pm =
119 ExtensionSystem::Get(profile_)->process_manager();
kinuko 2012/05/18 10:22:17 nit: indent
benwells 2012/05/22 13:15:03 Done.
120 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_->id());
121 if (host) {
122 GrantAccessToFileAndLaunch(file_path, mime_type, host);
123 return;
124 }
125
126 // The host isn't loaded yet, so we post a task to the queue for the host.
Mihai Parparita -not on Chrome 2012/05/18 04:26:04 Can this be racy (the host was about to be shut do
benwells 2012/05/18 04:56:55 Good point. I initially used AddPendingTask but it
Matt Perry 2012/05/18 19:02:41 Thanks for checking. Rather than checking if host
Matt Perry 2012/05/18 19:04:38 Sorry, I meant to say "if ShouldEnqueueTask return
benwells 2012/05/22 13:15:03 Done.
127 // This will load the background page, and then call our task.
128 extensions::LazyBackgroundTaskQueue* queue =
129 ExtensionSystem::Get(profile_)->lazy_background_task_queue();
Matt Perry 2012/05/18 19:02:41 indent += 2
benwells 2012/05/22 13:15:03 Done.
130 queue->AddPendingTask(profile_, extension_->id(),
131 base::Bind(&PlatformAppLauncher::GrantAccessToFileAndLaunch,
132 this, file_path, mime_type));
133 }
134
135 void GrantAccessToFileAndLaunch(const FilePath& file_path,
136 const std::string& mime_type,
137 ExtensionHost* host) {
138 // If there was an error loading the app page, |host| will be NULL.
139 if (!host) {
140 LOG(ERROR) << "Could not load app page for " << extension_->id();
141 return;
142 }
143
144 content::ChildProcessSecurityPolicy* policy =
145 content::ChildProcessSecurityPolicy::GetInstance();
146 int renderer_id = host->render_process_host()->GetID();
147
148 std::set<FilePath> filesets;
Mihai Parparita -not on Chrome 2012/05/18 04:26:04 Nit: this can be moved a few lines lower, since it
benwells 2012/05/22 13:15:03 Done.
149 // If the renderer already has permission to read these paths, we don't
150 // regrant, as this would overwrite any other permissions which the renderer
151 // may already have.
152 if (!policy->CanReadFile(renderer_id, file_path))
153 policy->GrantReadFile(renderer_id, file_path);
154
155 filesets.insert(file_path);
156
157 fileapi::IsolatedContext* isolated_context =
158 fileapi::IsolatedContext::GetInstance();
159 DCHECK(isolated_context);
160 std::string filesystem_id = isolated_context->RegisterIsolatedFileSystem(
161 filesets);
162 policy->GrantAccessFileSystem(renderer_id, filesystem_id);
163
164 extensions::AppEventRouter::DispatchOnLaunchedEventWithFileEntry(
165 profile_, extension_, ASCIIToUTF16(kViewIntent), mime_type,
166 filesystem_id, file_path.BaseName().value());
167 }
168
169 Profile* profile_;
170 const Extension* extension_;
171 const CommandLine* command_line_;
172
173 DISALLOW_COPY_AND_ASSIGN(PlatformAppLauncher);
174 };
175
176 } // namespace
177
178 namespace extensions {
179
180 void LaunchPlatformApp(Profile* profile,
181 const Extension* extension,
182 const CommandLine* command_line) {
183 // launcher will be freed when nothing has a reference to it. The message
184 // queue will retain a reference for any outstanding task, so when the
185 // launcher has finished it will be freed.
186 scoped_refptr<PlatformAppLauncher> launcher =
187 new PlatformAppLauncher(profile, extension, command_line);
188 launcher->Launch();
189 }
190
191 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698