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/chromeos/file_manager/filesystem_api_util.h"
15 #include "chrome/browser/chromeos/fileapi/external_file_url_util.h"
16 #include "chrome/browser/drive/drive_api_util.h"
17 #include "chrome/browser/plugins/plugin_prefs.h"
18 #include "chrome/browser/profiles/profile_manager.h"
19 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
20 #include "chrome/browser/ui/browser.h"
21 #include "chrome/browser/ui/browser_tabstrip.h"
22 #include "chrome/browser/ui/browser_window.h"
23 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
24 #include "chrome/common/chrome_content_client.h"
25 #include "chrome/common/chrome_paths.h"
26 #include "chrome/common/chrome_switches.h"
27 #include "content/public/browser/browser_thread.h"
28 #include "content/public/browser/plugin_service.h"
29 #include "content/public/common/pepper_plugin_info.h"
30 #include "net/base/filename_util.h"
32 using content::BrowserThread
;
33 using content::PluginService
;
35 namespace file_manager
{
39 const base::FilePath::CharType kPdfExtension
[] = FILE_PATH_LITERAL(".pdf");
40 const base::FilePath::CharType kSwfExtension
[] = FILE_PATH_LITERAL(".swf");
42 // List of file extensions viewable in the browser.
43 const base::FilePath::CharType
* kFileExtensionsViewableInBrowser
[] = {
44 FILE_PATH_LITERAL(".bmp"),
45 FILE_PATH_LITERAL(".ico"),
46 FILE_PATH_LITERAL(".jpg"),
47 FILE_PATH_LITERAL(".jpeg"),
48 FILE_PATH_LITERAL(".png"),
49 FILE_PATH_LITERAL(".webp"),
50 FILE_PATH_LITERAL(".gif"),
51 FILE_PATH_LITERAL(".txt"),
52 FILE_PATH_LITERAL(".html"),
53 FILE_PATH_LITERAL(".htm"),
54 FILE_PATH_LITERAL(".mhtml"),
55 FILE_PATH_LITERAL(".mht"),
56 FILE_PATH_LITERAL(".xhtml"),
57 FILE_PATH_LITERAL(".xht"),
58 FILE_PATH_LITERAL(".shtml"),
59 FILE_PATH_LITERAL(".svg"),
62 // Returns true if |file_path| is viewable in the browser (ex. HTML file).
63 bool IsViewableInBrowser(const base::FilePath
& file_path
) {
64 for (size_t i
= 0; i
< arraysize(kFileExtensionsViewableInBrowser
); i
++) {
65 if (file_path
.MatchesExtension(kFileExtensionsViewableInBrowser
[i
]))
71 bool IsPepperPluginEnabled(Profile
* profile
,
72 const base::FilePath
& plugin_path
) {
75 content::PepperPluginInfo
* pepper_info
=
76 PluginService::GetInstance()->GetRegisteredPpapiPluginInfo(plugin_path
);
80 scoped_refptr
<PluginPrefs
> plugin_prefs
= PluginPrefs::GetForProfile(profile
);
81 if (!plugin_prefs
.get())
84 return plugin_prefs
->IsPluginEnabled(pepper_info
->ToWebPluginInfo());
87 bool IsPdfPluginEnabled(Profile
* profile
) {
90 base::FilePath plugin_path
= base::FilePath::FromUTF8Unsafe(
91 ChromeContentClient::kPDFPluginPath
);
92 return IsPepperPluginEnabled(profile
, plugin_path
);
95 bool IsFlashPluginEnabled(Profile
* profile
) {
98 base::FilePath
plugin_path(
99 base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(
100 switches::kPpapiFlashPath
));
101 if (plugin_path
.empty())
102 PathService::Get(chrome::FILE_PEPPER_FLASH_PLUGIN
, &plugin_path
);
103 return IsPepperPluginEnabled(profile
, plugin_path
);
106 void OpenNewTab(Profile
* profile
, const GURL
& url
) {
107 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
109 // Check the validity of the pointer so that the closure from
110 // base::Bind(&OpenNewTab, profile) can be passed between threads.
111 if (!g_browser_process
->profile_manager()->IsValidProfile(profile
))
114 chrome::ScopedTabbedBrowserDisplayer
displayer(
115 profile
, chrome::HOST_DESKTOP_TYPE_ASH
);
116 chrome::AddSelectedTabWithURL(displayer
.browser(), url
,
117 ui::PAGE_TRANSITION_LINK
);
119 // Since the ScopedTabbedBrowserDisplayer does not guarantee that the
120 // browser will be shown on the active desktop, we ensure the visibility.
121 multi_user_util::MoveWindowToCurrentDesktop(
122 displayer
.browser()->window()->GetNativeWindow());
125 // Reads the alternate URL from a GDoc file. When it fails, returns a file URL
126 // for |file_path| as fallback.
127 // Note that an alternate url is a URL to open a hosted document.
128 GURL
ReadUrlFromGDocOnBlockingPool(const base::FilePath
& file_path
) {
129 GURL url
= drive::util::ReadUrlFromGDocFile(file_path
);
131 url
= net::FilePathToFileURL(file_path
);
137 bool OpenFileWithBrowser(Profile
* profile
,
138 const storage::FileSystemURL
& file_system_url
) {
139 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
142 const base::FilePath file_path
= file_system_url
.path();
144 // For things supported natively by the browser, we should open it
146 if (IsViewableInBrowser(file_path
) ||
147 ShouldBeOpenedWithPlugin(profile
, file_path
.Extension())) {
148 // Use external file URL if it is provided for the file system.
149 GURL page_url
= chromeos::FileSystemURLToExternalFileURL(file_system_url
);
150 if (page_url
.is_empty())
151 page_url
= net::FilePathToFileURL(file_path
);
153 OpenNewTab(profile
, page_url
);
157 if (drive::util::HasHostedDocumentExtension(file_path
)) {
158 if (file_manager::util::IsUnderNonNativeLocalPath(profile
, file_path
)) {
159 // The file is on a non-native volume. Use external file URL. If the file
160 // is on the drive volume, ExternalFileURLRequestJob redirects the URL to
161 // drive's web interface. Otherwise (e.g. MTP, FSP), the file is just
162 // downloaded in a browser tab.
164 chromeos::FileSystemURLToExternalFileURL(file_system_url
);
165 DCHECK(!url
.is_empty());
166 OpenNewTab(profile
, url
);
168 // The file is local (downloaded from an attachment or otherwise copied).
169 // Parse the file to extract the Docs url and open this url.
170 base::PostTaskAndReplyWithResult(
171 BrowserThread::GetBlockingPool(),
173 base::Bind(&ReadUrlFromGDocOnBlockingPool
, file_path
),
174 base::Bind(&OpenNewTab
, profile
));
179 // Failed to open the file of unknown type.
180 LOG(WARNING
) << "Unknown file type: " << file_path
.value();
184 // If a bundled plugin is enabled, we should open pdf/swf files in a tab.
185 bool ShouldBeOpenedWithPlugin(
187 const base::FilePath::StringType
& file_extension
) {
190 const base::FilePath file_path
=
191 base::FilePath::FromUTF8Unsafe("dummy").AddExtension(file_extension
);
192 if (file_path
.MatchesExtension(kPdfExtension
))
193 return IsPdfPluginEnabled(profile
);
194 if (file_path
.MatchesExtension(kSwfExtension
))
195 return IsFlashPluginEnabled(profile
);
200 } // namespace file_manager