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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/platform_app_launcher.cc
diff --git a/chrome/browser/extensions/platform_app_launcher.cc b/chrome/browser/extensions/platform_app_launcher.cc
new file mode 100644
index 0000000000000000000000000000000000000000..189bcf964b296a1ac09f3e83221e959106f20604
--- /dev/null
+++ b/chrome/browser/extensions/platform_app_launcher.cc
@@ -0,0 +1,191 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/platform_app_launcher.h"
+
+#include "base/command_line.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/extensions/api/app/app_api.h"
+#include "chrome/browser/extensions/extension_host.h"
+#include "chrome/browser/extensions/extension_process_manager.h"
+#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/extensions/lazy_background_task_queue.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_messages.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/child_process_security_policy.h"
+#include "content/public/browser/render_process_host.h"
+#include "net/base/mime_util.h"
+#include "net/base/net_util.h"
+#include "webkit/fileapi/isolated_context.h"
+#include "webkit/glue/web_intent_service_data.h"
+
+using content::BrowserThread;
+
+namespace {
+
+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.
+
+class PlatformAppLauncher
+ : public base::RefCountedThreadSafe<PlatformAppLauncher> {
+ public:
+ PlatformAppLauncher(Profile* profile,
+ const Extension* extension,
+ const CommandLine* command_line)
+ : profile_(profile),
+ extension_(extension),
+ command_line_(command_line) {}
+
+ void Launch() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (!command_line_ || !command_line_->GetArgs().size()) {
+ LaunchWithNoLaunchData();
+ return;
+ }
+
+ FilePath file_path(command_line_->GetArgs()[0]);
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(
+ &PlatformAppLauncher::GetMimeTypeAndLaunch, this, file_path));
+ }
+
+ private:
+ void LaunchWithNoLaunchData() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ extensions::AppEventRouter::DispatchOnLaunchedEvent(profile_, extension_);
+ }
+
+ void GetMimeTypeAndLaunch(const FilePath& file_path) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+ // If the file doesn't exist, or is a directory, launch with no launch data.
+ if (!file_util::PathExists(file_path) ||
+ file_util::DirectoryExists(file_path)) {
+ LOG(WARNING) << "No file exists with path " << file_path.value();
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
+ &PlatformAppLauncher::LaunchWithNoLaunchData, this));
+ return;
+ }
+
+ std::string mime_type;
+ // If we cannot obtain the MIME type, launch with no launch data.
+ if (!net::GetMimeTypeFromFile(file_path, &mime_type)) {
+ LOG(WARNING) << "Could not obtain MIME type for " << file_path.value();
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
+ &PlatformAppLauncher::LaunchWithNoLaunchData, this));
+ return;
+ }
+
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
+ &PlatformAppLauncher::LaunchWithMimeTypeAndPath, this, file_path,
+ mime_type));
+ }
+
+ void LaunchWithMimeTypeAndPath(const FilePath& file_path,
+ const std::string& mime_type) {
+ // Find the intent service from the platform app for the file being opened.
+ webkit_glue::WebIntentServiceData service;
+ bool found_service = false;
+
+ std::vector<webkit_glue::WebIntentServiceData> services =
+ extension_->intents_services();
+ for (size_t i = 0; i < services.size(); i++) {
+ std::string service_type_ascii = UTF16ToASCII(services[i].type);
+ if (services[i].action == ASCIIToUTF16(kViewIntent) &&
+ net::MatchesMimeType(service_type_ascii, mime_type)) {
+ service = services[i];
+ 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.
+ }
+ }
+
+ // If this app doesn't have an intent that supports the file, launch with
+ // no launch data.
+ if (!found_service) {
+ LOG(WARNING) << "Extension does not provide a valid intent for "
+ << file_path.value();
+ LaunchWithNoLaunchData();
+ return;
+ }
+
+ // We need to grant access to the file for the process associated with the
+ // extension. To do this we need the ExtensionHost, so we try and get it.
+ ExtensionProcessManager* pm =
+ ExtensionSystem::Get(profile_)->process_manager();
kinuko 2012/05/18 10:22:17 nit: indent
benwells 2012/05/22 13:15:03 Done.
+ ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_->id());
+ if (host) {
+ GrantAccessToFileAndLaunch(file_path, mime_type, host);
+ return;
+ }
+
+ // 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.
+ // This will load the background page, and then call our task.
+ extensions::LazyBackgroundTaskQueue* queue =
+ 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.
+ queue->AddPendingTask(profile_, extension_->id(),
+ base::Bind(&PlatformAppLauncher::GrantAccessToFileAndLaunch,
+ this, file_path, mime_type));
+ }
+
+ void GrantAccessToFileAndLaunch(const FilePath& file_path,
+ const std::string& mime_type,
+ ExtensionHost* host) {
+ // If there was an error loading the app page, |host| will be NULL.
+ if (!host) {
+ LOG(ERROR) << "Could not load app page for " << extension_->id();
+ return;
+ }
+
+ content::ChildProcessSecurityPolicy* policy =
+ content::ChildProcessSecurityPolicy::GetInstance();
+ int renderer_id = host->render_process_host()->GetID();
+
+ 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.
+ // If the renderer already has permission to read these paths, we don't
+ // regrant, as this would overwrite any other permissions which the renderer
+ // may already have.
+ if (!policy->CanReadFile(renderer_id, file_path))
+ policy->GrantReadFile(renderer_id, file_path);
+
+ filesets.insert(file_path);
+
+ fileapi::IsolatedContext* isolated_context =
+ fileapi::IsolatedContext::GetInstance();
+ DCHECK(isolated_context);
+ std::string filesystem_id = isolated_context->RegisterIsolatedFileSystem(
+ filesets);
+ policy->GrantAccessFileSystem(renderer_id, filesystem_id);
+
+ extensions::AppEventRouter::DispatchOnLaunchedEventWithFileEntry(
+ profile_, extension_, ASCIIToUTF16(kViewIntent), mime_type,
+ filesystem_id, file_path.BaseName().value());
+ }
+
+ Profile* profile_;
+ const Extension* extension_;
+ const CommandLine* command_line_;
+
+ DISALLOW_COPY_AND_ASSIGN(PlatformAppLauncher);
+};
+
+} // namespace
+
+namespace extensions {
+
+void LaunchPlatformApp(Profile* profile,
+ const Extension* extension,
+ const CommandLine* command_line) {
+ // launcher will be freed when nothing has a reference to it. The message
+ // queue will retain a reference for any outstanding task, so when the
+ // launcher has finished it will be freed.
+ scoped_refptr<PlatformAppLauncher> launcher =
+ new PlatformAppLauncher(profile, extension, command_line);
+ launcher->Launch();
+}
+
+} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698