1 // Copyright 2013 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.
5 #include "chrome/browser/chromeos/file_manager/open_with_browser.h"
8 #include "base/command_line.h"
9 #include "base/logging.h"
10 #include "base/path_service.h"
11 #include "base/threading/sequenced_worker_pool.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/chromeos/drive/file_system_util.h"
14 #include "chrome/browser/drive/drive_api_util.h"
15 #include "chrome/browser/plugins/plugin_prefs.h"
16 #include "chrome/browser/profiles/profile_manager.h"
17 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_tabstrip.h"
20 #include "chrome/browser/ui/browser_window.h"
21 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
22 #include "chrome/common/chrome_paths.h"
23 #include "chrome/common/chrome_switches.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/plugin_service.h"
26 #include "content/public/common/pepper_plugin_info.h"
27 #include "net/base/filename_util.h"
29 using content::BrowserThread;
30 using content::PluginService;
32 namespace file_manager {
36 const base::FilePath::CharType kPdfExtension[] = FILE_PATH_LITERAL(".pdf");
37 const base::FilePath::CharType kSwfExtension[] = FILE_PATH_LITERAL(".swf");
39 // List of file extensions viewable in the browser.
40 const base::FilePath::CharType* kFileExtensionsViewableInBrowser[] = {
41 FILE_PATH_LITERAL(".bmp"),
42 FILE_PATH_LITERAL(".ico"),
43 FILE_PATH_LITERAL(".jpg"),
44 FILE_PATH_LITERAL(".jpeg"),
45 FILE_PATH_LITERAL(".png"),
46 FILE_PATH_LITERAL(".webp"),
47 FILE_PATH_LITERAL(".gif"),
48 FILE_PATH_LITERAL(".txt"),
49 FILE_PATH_LITERAL(".html"),
50 FILE_PATH_LITERAL(".htm"),
51 FILE_PATH_LITERAL(".mhtml"),
52 FILE_PATH_LITERAL(".mht"),
53 FILE_PATH_LITERAL(".svg"),
56 // Returns true if |file_path| is viewable in the browser (ex. HTML file).
57 bool IsViewableInBrowser(const base::FilePath& file_path) {
58 for (size_t i = 0; i < arraysize(kFileExtensionsViewableInBrowser); i++) {
59 if (file_path.MatchesExtension(kFileExtensionsViewableInBrowser[i]))
65 bool IsPepperPluginEnabled(Profile* profile,
66 const base::FilePath& plugin_path) {
69 content::PepperPluginInfo* pepper_info =
70 PluginService::GetInstance()->GetRegisteredPpapiPluginInfo(plugin_path);
74 scoped_refptr<PluginPrefs> plugin_prefs = PluginPrefs::GetForProfile(profile);
75 if (!plugin_prefs.get())
78 return plugin_prefs->IsPluginEnabled(pepper_info->ToWebPluginInfo());
81 bool IsPdfPluginEnabled(Profile* profile) {
84 base::FilePath plugin_path;
85 PathService::Get(chrome::FILE_PDF_PLUGIN, &plugin_path);
86 return IsPepperPluginEnabled(profile, plugin_path);
89 bool IsFlashPluginEnabled(Profile* profile) {
92 base::FilePath plugin_path(
93 CommandLine::ForCurrentProcess()->GetSwitchValueNative(
94 switches::kPpapiFlashPath));
95 if (plugin_path.empty())
96 PathService::Get(chrome::FILE_PEPPER_FLASH_PLUGIN, &plugin_path);
97 return IsPepperPluginEnabled(profile, plugin_path);
100 void OpenNewTab(Profile* profile, const GURL& url) {
101 DCHECK_CURRENTLY_ON(BrowserThread::UI);
103 // Check the validity of the pointer so that the closure from
104 // base::Bind(&OpenNewTab, profile) can be passed between threads.
105 if (!g_browser_process->profile_manager()->IsValidProfile(profile))
108 chrome::ScopedTabbedBrowserDisplayer displayer(
109 profile, chrome::HOST_DESKTOP_TYPE_ASH);
110 chrome::AddSelectedTabWithURL(displayer.browser(), url,
111 content::PAGE_TRANSITION_LINK);
113 // Since the ScopedTabbedBrowserDisplayer does not guarantee that the
114 // browser will be shown on the active desktop, we ensure the visibility.
115 multi_user_util::MoveWindowToCurrentDesktop(
116 displayer.browser()->window()->GetNativeWindow());
119 // Reads the alternate URL from a GDoc file. When it fails, returns a file URL
120 // for |file_path| as fallback.
121 // Note that an alternate url is a URL to open a hosted document.
122 GURL ReadUrlFromGDocOnBlockingPool(const base::FilePath& file_path) {
123 GURL url = drive::util::ReadUrlFromGDocFile(file_path);
125 url = net::FilePathToFileURL(file_path);
131 bool OpenFileWithBrowser(Profile* profile, const base::FilePath& file_path) {
132 DCHECK_CURRENTLY_ON(BrowserThread::UI);
135 // For things supported natively by the browser, we should open it
137 if (IsViewableInBrowser(file_path) ||
138 ShouldBeOpenedWithPlugin(profile, file_path.Extension())) {
139 GURL page_url = net::FilePathToFileURL(file_path);
140 // Override drive resource to point to internal handler instead of file URL.
141 if (drive::util::IsUnderDriveMountPoint(file_path)) {
142 page_url = drive::util::FilePathToDriveURL(
143 drive::util::ExtractDrivePath(file_path));
145 OpenNewTab(profile, page_url);
149 if (drive::util::HasHostedDocumentExtension(file_path)) {
150 if (drive::util::IsUnderDriveMountPoint(file_path)) {
151 // The file is on Google Docs. Open with drive URL.
152 GURL url = drive::util::FilePathToDriveURL(
153 drive::util::ExtractDrivePath(file_path));
154 OpenNewTab(profile, url);
156 // The file is local (downloaded from an attachment or otherwise copied).
157 // Parse the file to extract the Docs url and open this url.
158 base::PostTaskAndReplyWithResult(
159 BrowserThread::GetBlockingPool(),
161 base::Bind(&ReadUrlFromGDocOnBlockingPool, file_path),
162 base::Bind(&OpenNewTab, profile));
167 // Failed to open the file of unknown type.
168 LOG(WARNING) << "Unknown file type: " << file_path.value();
172 // If a bundled plugin is enabled, we should open pdf/swf files in a tab.
173 bool ShouldBeOpenedWithPlugin(
175 const base::FilePath::StringType& file_extension) {
178 const base::FilePath file_path =
179 base::FilePath::FromUTF8Unsafe("dummy").AddExtension(file_extension);
180 if (file_path.MatchesExtension(kPdfExtension))
181 return IsPdfPluginEnabled(profile);
182 if (file_path.MatchesExtension(kSwfExtension))
183 return IsFlashPluginEnabled(profile);
188 } // namespace file_manager