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

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: Windows tests fixed 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
« no previous file with comments | « chrome/browser/extensions/platform_app_launcher.h ('k') | chrome/browser/ui/browser.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 using extensions::Extension;
32
33 namespace {
34
35 const char kViewIntent[] = "http://webintents.org/view";
36
37 class PlatformAppLauncher
38 : public base::RefCountedThreadSafe<PlatformAppLauncher> {
39 public:
40 PlatformAppLauncher(Profile* profile,
41 const Extension* extension,
42 const CommandLine* command_line)
43 : profile_(profile),
44 extension_(extension),
45 command_line_(command_line) {}
46
47 void Launch() {
48 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
49 if (!command_line_ || !command_line_->GetArgs().size()) {
50 LaunchWithNoLaunchData();
51 return;
52 }
53
54 FilePath file_path(command_line_->GetArgs()[0]);
55 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(
56 &PlatformAppLauncher::GetMimeTypeAndLaunch, this, file_path));
57 }
58
59 private:
60 friend class base::RefCountedThreadSafe<PlatformAppLauncher>;
61
62 virtual ~PlatformAppLauncher() {}
63
64 void LaunchWithNoLaunchData() {
65 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
66 extensions::AppEventRouter::DispatchOnLaunchedEvent(profile_, extension_);
67 }
68
69 void GetMimeTypeAndLaunch(const FilePath& file_path) {
70 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
71
72 // If the file doesn't exist, or is a directory, launch with no launch data.
73 if (!file_util::PathExists(file_path) ||
74 file_util::DirectoryExists(file_path)) {
75 LOG(WARNING) << "No file exists with path " << file_path.value();
76 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
77 &PlatformAppLauncher::LaunchWithNoLaunchData, this));
78 return;
79 }
80
81 std::string mime_type;
82 // If we cannot obtain the MIME type, launch with no launch data.
83 if (!net::GetMimeTypeFromFile(file_path, &mime_type)) {
84 LOG(WARNING) << "Could not obtain MIME type for " << file_path.value();
85 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
86 &PlatformAppLauncher::LaunchWithNoLaunchData, this));
87 return;
88 }
89
90 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
91 &PlatformAppLauncher::LaunchWithMimeTypeAndPath, this, file_path,
92 mime_type));
93 }
94
95 void LaunchWithMimeTypeAndPath(const FilePath& file_path,
96 const std::string& mime_type) {
97 // Find the intent service from the platform app for the file being opened.
98 webkit_glue::WebIntentServiceData service;
99 bool found_service = false;
100
101 std::vector<webkit_glue::WebIntentServiceData> services =
102 extension_->intents_services();
103 for (size_t i = 0; i < services.size(); i++) {
104 std::string service_type_ascii = UTF16ToASCII(services[i].type);
105 if (services[i].action == ASCIIToUTF16(kViewIntent) &&
106 net::MatchesMimeType(service_type_ascii, mime_type)) {
107 service = services[i];
108 found_service = true;
109 break;
110 }
111 }
112
113 // If this app doesn't have an intent that supports the file, launch with
114 // no launch data.
115 if (!found_service) {
116 LOG(WARNING) << "Extension does not provide a valid intent for "
117 << file_path.value();
118 LaunchWithNoLaunchData();
119 return;
120 }
121
122 // We need to grant access to the file for the process associated with the
123 // extension. To do this we need the ExtensionHost. This might not be
124 // available, or it might be in the process of being unloaded, in which case
125 // we can use the lazy background task queue to load the extension and then
126 // call back to us.
127 extensions::LazyBackgroundTaskQueue* queue =
128 ExtensionSystem::Get(profile_)->lazy_background_task_queue();
129 if (queue->ShouldEnqueueTask(profile_, extension_)) {
130 queue->AddPendingTask(profile_, extension_->id(),
131 base::Bind(&PlatformAppLauncher::GrantAccessToFileAndLaunch,
132 this, file_path, mime_type));
133 return;
134 }
135
136 ExtensionProcessManager* pm =
137 ExtensionSystem::Get(profile_)->process_manager();
138 ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_->id());
139 DCHECK(host);
140 GrantAccessToFileAndLaunch(file_path, mime_type, host);
141 }
142
143 void GrantAccessToFileAndLaunch(const FilePath& file_path,
144 const std::string& mime_type,
145 ExtensionHost* host) {
146 // If there was an error loading the app page, |host| will be NULL.
147 if (!host) {
148 LOG(ERROR) << "Could not load app page for " << extension_->id();
149 return;
150 }
151
152 content::ChildProcessSecurityPolicy* policy =
153 content::ChildProcessSecurityPolicy::GetInstance();
154 int renderer_id = host->render_process_host()->GetID();
155
156 // If the renderer already has permission to read these paths, we don't
157 // regrant, as this would overwrite any other permissions which the renderer
158 // may already have.
159 if (!policy->CanReadFile(renderer_id, file_path))
160 policy->GrantReadFile(renderer_id, file_path);
161
162 std::set<FilePath> filesets;
163 filesets.insert(file_path);
164
165 fileapi::IsolatedContext* isolated_context =
166 fileapi::IsolatedContext::GetInstance();
167 DCHECK(isolated_context);
168 std::string filesystem_id = isolated_context->RegisterIsolatedFileSystem(
169 filesets);
170 policy->GrantAccessFileSystem(renderer_id, filesystem_id);
171
172 extensions::AppEventRouter::DispatchOnLaunchedEventWithFileEntry(
173 profile_, extension_, ASCIIToUTF16(kViewIntent), filesystem_id,
174 file_path.BaseName());
175 }
176
177 Profile* profile_;
178 const Extension* extension_;
179 const CommandLine* command_line_;
180
181 DISALLOW_COPY_AND_ASSIGN(PlatformAppLauncher);
182 };
183
184 } // namespace
185
186 namespace extensions {
187
188 void LaunchPlatformApp(Profile* profile,
189 const Extension* extension,
190 const CommandLine* command_line) {
191 // launcher will be freed when nothing has a reference to it. The message
192 // queue will retain a reference for any outstanding task, so when the
193 // launcher has finished it will be freed.
194 scoped_refptr<PlatformAppLauncher> launcher =
195 new PlatformAppLauncher(profile, extension, command_line);
196 launcher->Launch();
197 }
198
199 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/platform_app_launcher.h ('k') | chrome/browser/ui/browser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698