• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/chromeos/file_manager/open_with_browser.h"
6 
7 #include "base/bind.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/plugins/plugin_prefs.h"
15 #include "chrome/browser/profiles/profile_manager.h"
16 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_tabstrip.h"
19 #include "chrome/browser/ui/browser_window.h"
20 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
21 #include "chrome/common/chrome_paths.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/plugin_service.h"
25 #include "content/public/common/pepper_plugin_info.h"
26 #include "net/base/filename_util.h"
27 
28 using content::BrowserThread;
29 using content::PluginService;
30 
31 namespace file_manager {
32 namespace util {
33 namespace {
34 
35 const base::FilePath::CharType kPdfExtension[] = FILE_PATH_LITERAL(".pdf");
36 const base::FilePath::CharType kSwfExtension[] = FILE_PATH_LITERAL(".swf");
37 
38 // List of file extensions viewable in the browser.
39 const base::FilePath::CharType* kFileExtensionsViewableInBrowser[] = {
40   FILE_PATH_LITERAL(".bmp"),
41   FILE_PATH_LITERAL(".ico"),
42   FILE_PATH_LITERAL(".jpg"),
43   FILE_PATH_LITERAL(".jpeg"),
44   FILE_PATH_LITERAL(".png"),
45   FILE_PATH_LITERAL(".webp"),
46   FILE_PATH_LITERAL(".gif"),
47   FILE_PATH_LITERAL(".txt"),
48   FILE_PATH_LITERAL(".html"),
49   FILE_PATH_LITERAL(".htm"),
50   FILE_PATH_LITERAL(".mhtml"),
51   FILE_PATH_LITERAL(".mht"),
52   FILE_PATH_LITERAL(".svg"),
53 };
54 
55 // Returns true if |file_path| is viewable in the browser (ex. HTML file).
IsViewableInBrowser(const base::FilePath & file_path)56 bool IsViewableInBrowser(const base::FilePath& file_path) {
57   for (size_t i = 0; i < arraysize(kFileExtensionsViewableInBrowser); i++) {
58     if (file_path.MatchesExtension(kFileExtensionsViewableInBrowser[i]))
59       return true;
60   }
61   return false;
62 }
63 
IsPepperPluginEnabled(Profile * profile,const base::FilePath & plugin_path)64 bool IsPepperPluginEnabled(Profile* profile,
65                            const base::FilePath& plugin_path) {
66   DCHECK(profile);
67 
68   content::PepperPluginInfo* pepper_info =
69       PluginService::GetInstance()->GetRegisteredPpapiPluginInfo(plugin_path);
70   if (!pepper_info)
71     return false;
72 
73   scoped_refptr<PluginPrefs> plugin_prefs = PluginPrefs::GetForProfile(profile);
74   if (!plugin_prefs.get())
75     return false;
76 
77   return plugin_prefs->IsPluginEnabled(pepper_info->ToWebPluginInfo());
78 }
79 
IsPdfPluginEnabled(Profile * profile)80 bool IsPdfPluginEnabled(Profile* profile) {
81   DCHECK(profile);
82 
83   base::FilePath plugin_path;
84   PathService::Get(chrome::FILE_PDF_PLUGIN, &plugin_path);
85   return IsPepperPluginEnabled(profile, plugin_path);
86 }
87 
IsFlashPluginEnabled(Profile * profile)88 bool IsFlashPluginEnabled(Profile* profile) {
89   DCHECK(profile);
90 
91   base::FilePath plugin_path(
92       CommandLine::ForCurrentProcess()->GetSwitchValueNative(
93           switches::kPpapiFlashPath));
94   if (plugin_path.empty())
95     PathService::Get(chrome::FILE_PEPPER_FLASH_PLUGIN, &plugin_path);
96   return IsPepperPluginEnabled(profile, plugin_path);
97 }
98 
OpenNewTab(Profile * profile,const GURL & url)99 void OpenNewTab(Profile* profile, const GURL& url) {
100   DCHECK_CURRENTLY_ON(BrowserThread::UI);
101 
102   // Check the validity of the pointer so that the closure from
103   // base::Bind(&OpenNewTab, profile) can be passed between threads.
104   if (!g_browser_process->profile_manager()->IsValidProfile(profile))
105     return;
106 
107   chrome::ScopedTabbedBrowserDisplayer displayer(
108       profile, chrome::HOST_DESKTOP_TYPE_ASH);
109   chrome::AddSelectedTabWithURL(displayer.browser(), url,
110       content::PAGE_TRANSITION_LINK);
111 
112   // Since the ScopedTabbedBrowserDisplayer does not guarantee that the
113   // browser will be shown on the active desktop, we ensure the visibility.
114   multi_user_util::MoveWindowToCurrentDesktop(
115       displayer.browser()->window()->GetNativeWindow());
116 }
117 
118 // Reads the alternate URL from a GDoc file. When it fails, returns a file URL
119 // for |file_path| as fallback.
120 // Note that an alternate url is a URL to open a hosted document.
ReadUrlFromGDocOnBlockingPool(const base::FilePath & file_path)121 GURL ReadUrlFromGDocOnBlockingPool(const base::FilePath& file_path) {
122   GURL url = drive::util::ReadUrlFromGDocFile(file_path);
123   if (url.is_empty())
124     url = net::FilePathToFileURL(file_path);
125   return url;
126 }
127 
128 }  // namespace
129 
OpenFileWithBrowser(Profile * profile,const base::FilePath & file_path)130 bool OpenFileWithBrowser(Profile* profile, const base::FilePath& file_path) {
131   DCHECK_CURRENTLY_ON(BrowserThread::UI);
132   DCHECK(profile);
133 
134   // For things supported natively by the browser, we should open it
135   // in a tab.
136   if (IsViewableInBrowser(file_path) ||
137       ShouldBeOpenedWithPlugin(profile, file_path.Extension())) {
138     GURL page_url = net::FilePathToFileURL(file_path);
139     // Override drive resource to point to internal handler instead of file URL.
140     if (drive::util::IsUnderDriveMountPoint(file_path)) {
141       page_url = drive::util::FilePathToDriveURL(
142           drive::util::ExtractDrivePath(file_path));
143     }
144     OpenNewTab(profile, page_url);
145     return true;
146   }
147 
148   if (drive::util::HasGDocFileExtension(file_path)) {
149     if (drive::util::IsUnderDriveMountPoint(file_path)) {
150       // The file is on Google Docs. Open with drive URL.
151       GURL url = drive::util::FilePathToDriveURL(
152           drive::util::ExtractDrivePath(file_path));
153       OpenNewTab(profile, url);
154     } else {
155       // The file is local (downloaded from an attachment or otherwise copied).
156       // Parse the file to extract the Docs url and open this url.
157       base::PostTaskAndReplyWithResult(
158           BrowserThread::GetBlockingPool(),
159           FROM_HERE,
160           base::Bind(&ReadUrlFromGDocOnBlockingPool, file_path),
161           base::Bind(&OpenNewTab, profile));
162     }
163     return true;
164   }
165 
166   // Failed to open the file of unknown type.
167   LOG(WARNING) << "Unknown file type: " << file_path.value();
168   return false;
169 }
170 
171 // If a bundled plugin is enabled, we should open pdf/swf files in a tab.
ShouldBeOpenedWithPlugin(Profile * profile,const base::FilePath::StringType & file_extension)172 bool ShouldBeOpenedWithPlugin(
173     Profile* profile,
174     const base::FilePath::StringType& file_extension) {
175   DCHECK(profile);
176 
177   const base::FilePath file_path =
178       base::FilePath::FromUTF8Unsafe("dummy").AddExtension(file_extension);
179   if (file_path.MatchesExtension(kPdfExtension))
180     return IsPdfPluginEnabled(profile);
181   if (file_path.MatchesExtension(kSwfExtension))
182     return IsFlashPluginEnabled(profile);
183   return false;
184 }
185 
186 }  // namespace util
187 }  // namespace file_manager
188