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

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: 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/extensions/platform_app_launcher.h ('k') | chrome/browser/ui/browser.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..47ea21af115638aaefce32bffc5c5171b07a6b10
--- /dev/null
+++ b/chrome/browser/extensions/platform_app_launcher.cc
@@ -0,0 +1,199 @@
+// 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;
+using extensions::Extension;
+
+namespace {
+
+const char kViewIntent[] = "http://webintents.org/view";
+
+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:
+ friend class base::RefCountedThreadSafe<PlatformAppLauncher>;
+
+ virtual ~PlatformAppLauncher() {}
+
+ 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;
+ break;
+ }
+ }
+
+ // 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. This might not be
+ // available, or it might be in the process of being unloaded, in which case
+ // we can use the lazy background task queue to load the extension and then
+ // call back to us.
+ extensions::LazyBackgroundTaskQueue* queue =
+ ExtensionSystem::Get(profile_)->lazy_background_task_queue();
+ if (queue->ShouldEnqueueTask(profile_, extension_)) {
+ queue->AddPendingTask(profile_, extension_->id(),
+ base::Bind(&PlatformAppLauncher::GrantAccessToFileAndLaunch,
+ this, file_path, mime_type));
+ return;
+ }
+
+ ExtensionProcessManager* pm =
+ ExtensionSystem::Get(profile_)->process_manager();
+ ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_->id());
+ DCHECK(host);
+ GrantAccessToFileAndLaunch(file_path, mime_type, host);
+ }
+
+ 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();
+
+ // 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);
+
+ std::set<FilePath> filesets;
+ 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), filesystem_id,
+ file_path.BaseName());
+ }
+
+ 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
« 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