This source file includes following definitions.
- MakePathAbsolute
- GetAbsolutePathFromCommandLine
- LaunchPlatformAppWithNoData
- file_path_
- Launch
- LaunchWithHandler
- OnFileValid
- OnFileInvalid
- GetMimeTypeAndLaunch
- GetMimeTypeAndLaunchForDriveFile
- OnGotDriveFile
- LaunchWithNoLaunchData
- LaunchWithMimeType
- GrantAccessToFileAndLaunch
- LaunchPlatformAppWithCommandLine
- LaunchPlatformAppWithPath
- LaunchPlatformApp
- LaunchPlatformAppWithFileHandler
- RestartPlatformApp
- LaunchPlatformAppWithUrl
#include "apps/launcher.h"
#include "apps/apps_client.h"
#include "apps/browser/api/app_runtime/app_runtime_api.h"
#include "apps/browser/file_handler_util.h"
#include "apps/common/api/app_runtime.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h"
#include "chrome/browser/extensions/api/file_system/file_system_api.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_host.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/lazy_background_task_queue.h"
#include "extensions/browser/process_manager.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_messages.h"
#include "extensions/common/manifest_handlers/kiosk_mode_info.h"
#include "net/base/mime_util.h"
#include "net/base/net_util.h"
#include "url/gurl.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/drive/file_errors.h"
#include "chrome/browser/chromeos/drive/file_system_interface.h"
#include "chrome/browser/chromeos/drive/file_system_util.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#endif
#if defined(OS_WIN)
#include "win8/util/win8_util.h"
#endif
namespace app_runtime = apps::api::app_runtime;
using apps::file_handler_util::GrantedFileEntry;
using content::BrowserThread;
using extensions::app_file_handler_util::CheckWritableFiles;
using extensions::app_file_handler_util::FileHandlerForId;
using extensions::app_file_handler_util::FileHandlerCanHandleFile;
using extensions::app_file_handler_util::FirstFileHandlerForFile;
using extensions::app_file_handler_util::CreateFileEntry;
using extensions::app_file_handler_util::HasFileSystemWritePermission;
using extensions::EventRouter;
using extensions::Extension;
using extensions::ExtensionHost;
using extensions::ExtensionSystem;
namespace apps {
namespace {
const char kFallbackMimeType[] = "application/octet-stream";
bool MakePathAbsolute(const base::FilePath& current_directory,
base::FilePath* file_path) {
DCHECK(file_path);
if (file_path->IsAbsolute())
return true;
if (current_directory.empty()) {
*file_path = base::MakeAbsoluteFilePath(*file_path);
return !file_path->empty();
}
if (!current_directory.IsAbsolute())
return false;
*file_path = current_directory.Append(*file_path);
return true;
}
bool GetAbsolutePathFromCommandLine(const CommandLine& command_line,
const base::FilePath& current_directory,
base::FilePath* path) {
if (!command_line.GetArgs().size())
return false;
base::FilePath relative_path(command_line.GetArgs()[0]);
base::FilePath absolute_path(relative_path);
if (!MakePathAbsolute(current_directory, &absolute_path)) {
LOG(WARNING) << "Cannot make absolute path from " << relative_path.value();
return false;
}
*path = absolute_path;
return true;
}
void LaunchPlatformAppWithNoData(Profile* profile, const Extension* extension) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
AppEventRouter::DispatchOnLaunchedEvent(profile, extension);
}
class PlatformAppPathLauncher
: public base::RefCountedThreadSafe<PlatformAppPathLauncher> {
public:
PlatformAppPathLauncher(Profile* profile,
const Extension* extension,
const base::FilePath& file_path)
: profile_(profile), extension_(extension), file_path_(file_path) {}
void Launch() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (file_path_.empty()) {
LaunchPlatformAppWithNoData(profile_, extension_);
return;
}
DCHECK(file_path_.IsAbsolute());
if (HasFileSystemWritePermission(extension_)) {
std::vector<base::FilePath> paths;
paths.push_back(file_path_);
CheckWritableFiles(
paths,
profile_,
false,
base::Bind(&PlatformAppPathLauncher::OnFileValid, this),
base::Bind(&PlatformAppPathLauncher::OnFileInvalid, this));
return;
}
OnFileValid();
}
void LaunchWithHandler(const std::string& handler_id) {
handler_id_ = handler_id;
Launch();
}
private:
friend class base::RefCountedThreadSafe<PlatformAppPathLauncher>;
virtual ~PlatformAppPathLauncher() {}
void OnFileValid() {
#if defined(OS_CHROMEOS)
if (drive::util::IsUnderDriveMountPoint(file_path_)) {
PlatformAppPathLauncher::GetMimeTypeAndLaunchForDriveFile();
return;
}
#endif
BrowserThread::PostTask(
BrowserThread::FILE,
FROM_HERE,
base::Bind(&PlatformAppPathLauncher::GetMimeTypeAndLaunch, this));
}
void OnFileInvalid(const base::FilePath& ) {
LaunchWithNoLaunchData();
}
void GetMimeTypeAndLaunch() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
if (!base::PathExists(file_path_) ||
base::DirectoryExists(file_path_)) {
LOG(WARNING) << "No file exists with path " << file_path_.value();
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
&PlatformAppPathLauncher::LaunchWithNoLaunchData, this));
return;
}
std::string mime_type;
if (!net::GetMimeTypeFromFile(file_path_, &mime_type))
mime_type = kFallbackMimeType;
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
&PlatformAppPathLauncher::LaunchWithMimeType, this, mime_type));
}
#if defined(OS_CHROMEOS)
void GetMimeTypeAndLaunchForDriveFile() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
drive::FileSystemInterface* file_system =
drive::util::GetFileSystemByProfile(profile_);
if (!file_system) {
LaunchWithNoLaunchData();
return;
}
file_system->GetFile(
drive::util::ExtractDrivePath(file_path_),
base::Bind(&PlatformAppPathLauncher::OnGotDriveFile, this));
}
void OnGotDriveFile(drive::FileError error,
const base::FilePath& file_path,
scoped_ptr<drive::ResourceEntry> entry) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (error != drive::FILE_ERROR_OK ||
!entry || entry->file_specific_info().is_hosted_document()) {
LaunchWithNoLaunchData();
return;
}
const std::string& mime_type =
entry->file_specific_info().content_mime_type();
LaunchWithMimeType(mime_type.empty() ? kFallbackMimeType : mime_type);
}
#endif
void LaunchWithNoLaunchData() {
LaunchPlatformAppWithNoData(profile_, extension_);
}
void LaunchWithMimeType(const std::string& mime_type) {
const extensions::FileHandlerInfo* handler = NULL;
if (!handler_id_.empty())
handler = FileHandlerForId(*extension_, handler_id_);
else
handler = FirstFileHandlerForFile(*extension_, mime_type, file_path_);
if (handler && !FileHandlerCanHandleFile(*handler, mime_type, file_path_)) {
LOG(WARNING) << "Extension does not provide a valid file handler for "
<< file_path_.value();
LaunchWithNoLaunchData();
return;
}
if (!handler) {
LOG(WARNING) << "Extension does not provide a valid file handler for "
<< file_path_.value();
LaunchWithNoLaunchData();
return;
}
if (handler_id_.empty())
handler_id_ = handler->id;
extensions::LazyBackgroundTaskQueue* queue =
ExtensionSystem::Get(profile_)->lazy_background_task_queue();
if (queue->ShouldEnqueueTask(profile_, extension_)) {
queue->AddPendingTask(profile_, extension_->id(), base::Bind(
&PlatformAppPathLauncher::GrantAccessToFileAndLaunch,
this, mime_type));
return;
}
extensions::ProcessManager* process_manager =
ExtensionSystem::Get(profile_)->process_manager();
ExtensionHost* host =
process_manager->GetBackgroundHostForExtension(extension_->id());
DCHECK(host);
GrantAccessToFileAndLaunch(mime_type, host);
}
void GrantAccessToFileAndLaunch(const std::string& mime_type,
ExtensionHost* host) {
if (!host) {
LOG(ERROR) << "Could not load app page for " << extension_->id();
return;
}
GrantedFileEntry file_entry =
CreateFileEntry(profile_,
extension_,
host->render_process_host()->GetID(),
file_path_,
false);
AppEventRouter::DispatchOnLaunchedEventWithFileEntry(
profile_, extension_, handler_id_, mime_type, file_entry);
}
Profile* profile_;
const Extension* extension_;
const base::FilePath file_path_;
std::string handler_id_;
DISALLOW_COPY_AND_ASSIGN(PlatformAppPathLauncher);
};
}
void LaunchPlatformAppWithCommandLine(Profile* profile,
const Extension* extension,
const CommandLine& command_line,
const base::FilePath& current_directory) {
if (!AppsClient::Get()->CheckAppLaunch(profile, extension))
return;
if (extensions::KioskModeInfo::IsKioskOnly(extension)) {
bool in_kiosk_mode = false;
#if defined(OS_CHROMEOS)
chromeos::UserManager* user_manager = chromeos::UserManager::Get();
in_kiosk_mode = user_manager && user_manager->IsLoggedInAsKioskApp();
#endif
if (!in_kiosk_mode) {
LOG(ERROR) << "App with 'kiosk_only' attribute must be run in "
<< " ChromeOS kiosk mode.";
NOTREACHED();
return;
}
}
base::FilePath path;
if (!GetAbsolutePathFromCommandLine(command_line, current_directory, &path)) {
LaunchPlatformAppWithNoData(profile, extension);
return;
}
LaunchPlatformAppWithPath(profile, extension, path);
}
void LaunchPlatformAppWithPath(Profile* profile,
const Extension* extension,
const base::FilePath& file_path) {
scoped_refptr<PlatformAppPathLauncher> launcher =
new PlatformAppPathLauncher(profile, extension, file_path);
launcher->Launch();
}
void LaunchPlatformApp(Profile* profile, const Extension* extension) {
LaunchPlatformAppWithCommandLine(profile,
extension,
CommandLine(CommandLine::NO_PROGRAM),
base::FilePath());
}
void LaunchPlatformAppWithFileHandler(Profile* profile,
const Extension* extension,
const std::string& handler_id,
const base::FilePath& file_path) {
scoped_refptr<PlatformAppPathLauncher> launcher =
new PlatformAppPathLauncher(profile, extension, file_path);
launcher->LaunchWithHandler(handler_id);
}
void RestartPlatformApp(Profile* profile, const Extension* extension) {
#if defined(OS_WIN)
if (win8::IsSingleWindowMetroMode())
return;
#endif
EventRouter* event_router = EventRouter::Get(profile);
bool listening_to_restart = event_router->
ExtensionHasEventListener(extension->id(),
app_runtime::OnRestarted::kEventName);
if (listening_to_restart) {
AppEventRouter::DispatchOnRestartedEvent(profile, extension);
return;
}
extensions::ExtensionPrefs* extension_prefs =
extensions::ExtensionPrefs::Get(profile);
bool had_windows = extension_prefs->IsActive(extension->id());
extension_prefs->SetIsActive(extension->id(), false);
bool listening_to_launch = event_router->
ExtensionHasEventListener(extension->id(),
app_runtime::OnLaunched::kEventName);
if (listening_to_launch && had_windows)
LaunchPlatformAppWithNoData(profile, extension);
}
void LaunchPlatformAppWithUrl(Profile* profile,
const Extension* extension,
const std::string& handler_id,
const GURL& url,
const GURL& referrer_url) {
AppEventRouter::DispatchOnLaunchedEventWithUrl(
profile, extension, handler_id, url, referrer_url);
}
}