- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / file_manager / open_with_browser.cc
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/extensions/api/file_handlers/app_file_handler_util.h"
15 #include "chrome/browser/plugins/plugin_prefs.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/profiles/profile_manager.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/browser/ui/simple_message_box.h"
23 #include "chrome/common/chrome_paths.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "chromeos/chromeos_switches.h"
26 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/plugin_service.h"
28 #include "content/public/common/pepper_plugin_info.h"
29 #include "content/public/common/webplugininfo.h"
30 #include "net/base/net_util.h"
31
32 using content::BrowserThread;
33 using content::PluginService;
34
35 namespace file_manager {
36 namespace util {
37 namespace {
38
39 const base::FilePath::CharType kPdfExtension[] = FILE_PATH_LITERAL(".pdf");
40 const base::FilePath::CharType kSwfExtension[] = FILE_PATH_LITERAL(".swf");
41
42 // List of file extensions viewable in the browser.
43 const base::FilePath::CharType* kFileExtensionsViewableInBrowser[] = {
44 #if defined(GOOGLE_CHROME_BUILD)
45   FILE_PATH_LITERAL(".pdf"),
46   FILE_PATH_LITERAL(".swf"),
47 #endif
48   FILE_PATH_LITERAL(".bmp"),
49   FILE_PATH_LITERAL(".jpg"),
50   FILE_PATH_LITERAL(".jpeg"),
51   FILE_PATH_LITERAL(".png"),
52   FILE_PATH_LITERAL(".webp"),
53   FILE_PATH_LITERAL(".gif"),
54   FILE_PATH_LITERAL(".txt"),
55   FILE_PATH_LITERAL(".html"),
56   FILE_PATH_LITERAL(".htm"),
57   FILE_PATH_LITERAL(".mhtml"),
58   FILE_PATH_LITERAL(".mht"),
59   FILE_PATH_LITERAL(".svg"),
60 };
61
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]))
66       return true;
67   }
68   return false;
69 }
70
71 bool IsPepperPluginEnabled(Profile* profile,
72                            const base::FilePath& plugin_path) {
73   DCHECK(profile);
74
75   content::PepperPluginInfo* pepper_info =
76       PluginService::GetInstance()->GetRegisteredPpapiPluginInfo(plugin_path);
77   if (!pepper_info)
78     return false;
79
80   scoped_refptr<PluginPrefs> plugin_prefs = PluginPrefs::GetForProfile(profile);
81   if (!plugin_prefs.get())
82     return false;
83
84   return plugin_prefs->IsPluginEnabled(pepper_info->ToWebPluginInfo());
85 }
86
87 bool IsPdfPluginEnabled(Profile* profile) {
88   DCHECK(profile);
89
90   base::FilePath plugin_path;
91   PathService::Get(chrome::FILE_PDF_PLUGIN, &plugin_path);
92   return IsPepperPluginEnabled(profile, plugin_path);
93 }
94
95 bool IsFlashPluginEnabled(Profile* profile) {
96   DCHECK(profile);
97
98   base::FilePath plugin_path(
99       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);
104 }
105
106 void OpenNewTab(Profile* profile, const GURL& url) {
107   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
108
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))
112     return;
113
114   chrome::ScopedTabbedBrowserDisplayer displayer(
115       profile, chrome::HOST_DESKTOP_TYPE_ASH);
116   chrome::AddSelectedTabWithURL(displayer.browser(), url,
117       content::PAGE_TRANSITION_LINK);
118 }
119
120 // Reads the alternate URL from a GDoc file. When it fails, returns a file URL
121 // for |file_path| as fallback.
122 // Note that an alternate url is a URL to open a hosted document.
123 GURL ReadUrlFromGDocOnBlockingPool(const base::FilePath& file_path) {
124   GURL url = drive::util::ReadUrlFromGDocFile(file_path);
125   if (url.is_empty())
126     url = net::FilePathToFileURL(file_path);
127   return url;
128 }
129
130 }  // namespace
131
132 bool OpenFileWithBrowser(Profile* profile, const base::FilePath& file_path) {
133   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
134   DCHECK(profile);
135
136   // For things supported natively by the browser, we should open it
137   // in a tab.
138   if (IsViewableInBrowser(file_path) ||
139       ShouldBeOpenedWithPlugin(profile, file_path.Extension())) {
140     GURL page_url = net::FilePathToFileURL(file_path);
141     // Override drive resource to point to internal handler instead of file URL.
142     if (drive::util::IsUnderDriveMountPoint(file_path)) {
143       page_url = drive::util::FilePathToDriveURL(
144           drive::util::ExtractDrivePath(file_path));
145     }
146     OpenNewTab(profile, page_url);
147     return true;
148   }
149
150   if (drive::util::HasGDocFileExtension(file_path)) {
151     if (drive::util::IsUnderDriveMountPoint(file_path)) {
152       // The file is on Google Docs. Open with drive URL.
153       GURL url = drive::util::FilePathToDriveURL(
154           drive::util::ExtractDrivePath(file_path));
155       OpenNewTab(profile, url);
156     } else {
157       // The file is local (downloaded from an attachment or otherwise copied).
158       // Parse the file to extract the Docs url and open this url.
159       base::PostTaskAndReplyWithResult(
160           BrowserThread::GetBlockingPool(),
161           FROM_HERE,
162           base::Bind(&ReadUrlFromGDocOnBlockingPool, file_path),
163           base::Bind(&OpenNewTab, profile));
164     }
165     return true;
166   }
167
168   // Failed to open the file of unknown type.
169   LOG(WARNING) << "Unknown file type: " << file_path.value();
170   return false;
171 }
172
173 // If a bundled plugin is enabled, we should open pdf/swf files in a tab.
174 bool ShouldBeOpenedWithPlugin(
175     Profile* profile,
176     const base::FilePath::StringType& file_extension) {
177   DCHECK(profile);
178
179   const base::FilePath file_path =
180       base::FilePath::FromUTF8Unsafe("dummy").AddExtension(file_extension);
181   if (file_path.MatchesExtension(kPdfExtension))
182     return IsPdfPluginEnabled(profile);
183   if (file_path.MatchesExtension(kSwfExtension))
184     return IsFlashPluginEnabled(profile);
185   return false;
186 }
187
188 }  // namespace util
189 }  // namespace file_manager