summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos/file_manager/open_with_browser.cc
blob: 7384caf32085c2db5669a969834b5fcbb8958ae0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/file_manager/open_with_browser.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/threading/sequenced_worker_pool.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/drive/file_system_util.h"
#include "chrome/browser/chromeos/file_manager/filesystem_api_util.h"
#include "chrome/browser/chromeos/fileapi/external_file_url_util.h"
#include "chrome/browser/drive/drive_api_util.h"
#include "chrome/browser/plugins/plugin_prefs.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/common/pepper_plugin_info.h"
#include "net/base/filename_util.h"

using content::BrowserThread;
using content::PluginService;

namespace file_manager {
namespace util {
namespace {

const base::FilePath::CharType kPdfExtension[] = FILE_PATH_LITERAL(".pdf");
const base::FilePath::CharType kSwfExtension[] = FILE_PATH_LITERAL(".swf");

// List of file extensions viewable in the browser.
const base::FilePath::CharType* kFileExtensionsViewableInBrowser[] = {
  FILE_PATH_LITERAL(".bmp"),
  FILE_PATH_LITERAL(".ico"),
  FILE_PATH_LITERAL(".jpg"),
  FILE_PATH_LITERAL(".jpeg"),
  FILE_PATH_LITERAL(".png"),
  FILE_PATH_LITERAL(".webp"),
  FILE_PATH_LITERAL(".gif"),
  FILE_PATH_LITERAL(".txt"),
  FILE_PATH_LITERAL(".html"),
  FILE_PATH_LITERAL(".htm"),
  FILE_PATH_LITERAL(".mhtml"),
  FILE_PATH_LITERAL(".mht"),
  FILE_PATH_LITERAL(".xhtml"),
  FILE_PATH_LITERAL(".xht"),
  FILE_PATH_LITERAL(".shtml"),
  FILE_PATH_LITERAL(".svg"),
};

// Returns true if |file_path| is viewable in the browser (ex. HTML file).
bool IsViewableInBrowser(const base::FilePath& file_path) {
  for (size_t i = 0; i < arraysize(kFileExtensionsViewableInBrowser); i++) {
    if (file_path.MatchesExtension(kFileExtensionsViewableInBrowser[i]))
      return true;
  }
  return false;
}

bool IsPepperPluginEnabled(Profile* profile,
                           const base::FilePath& plugin_path) {
  DCHECK(profile);

  content::PepperPluginInfo* pepper_info =
      PluginService::GetInstance()->GetRegisteredPpapiPluginInfo(plugin_path);
  if (!pepper_info)
    return false;

  scoped_refptr<PluginPrefs> plugin_prefs = PluginPrefs::GetForProfile(profile);
  if (!plugin_prefs.get())
    return false;

  return plugin_prefs->IsPluginEnabled(pepper_info->ToWebPluginInfo());
}

bool IsPdfPluginEnabled(Profile* profile) {
  DCHECK(profile);

  base::FilePath plugin_path = base::FilePath::FromUTF8Unsafe(
      ChromeContentClient::kPDFPluginPath);
  return IsPepperPluginEnabled(profile, plugin_path);
}

bool IsFlashPluginEnabled(Profile* profile) {
  DCHECK(profile);

  base::FilePath plugin_path(
      base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(
          switches::kPpapiFlashPath));
  if (plugin_path.empty())
    PathService::Get(chrome::FILE_PEPPER_FLASH_PLUGIN, &plugin_path);
  return IsPepperPluginEnabled(profile, plugin_path);
}

void OpenNewTab(Profile* profile, const GURL& url) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // Check the validity of the pointer so that the closure from
  // base::Bind(&OpenNewTab, profile) can be passed between threads.
  if (!g_browser_process->profile_manager()->IsValidProfile(profile))
    return;

  chrome::ScopedTabbedBrowserDisplayer displayer(
      profile, chrome::HOST_DESKTOP_TYPE_ASH);
  chrome::AddSelectedTabWithURL(displayer.browser(), url,
      ui::PAGE_TRANSITION_LINK);

  // Since the ScopedTabbedBrowserDisplayer does not guarantee that the
  // browser will be shown on the active desktop, we ensure the visibility.
  multi_user_util::MoveWindowToCurrentDesktop(
      displayer.browser()->window()->GetNativeWindow());
}

// Reads the alternate URL from a GDoc file. When it fails, returns a file URL
// for |file_path| as fallback.
// Note that an alternate url is a URL to open a hosted document.
GURL ReadUrlFromGDocOnBlockingPool(const base::FilePath& file_path) {
  GURL url = drive::util::ReadUrlFromGDocFile(file_path);
  if (url.is_empty())
    url = net::FilePathToFileURL(file_path);
  return url;
}

}  // namespace

bool OpenFileWithBrowser(Profile* profile,
                         const storage::FileSystemURL& file_system_url) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(profile);

  const base::FilePath file_path = file_system_url.path();

  // For things supported natively by the browser, we should open it
  // in a tab.
  if (IsViewableInBrowser(file_path) ||
      ShouldBeOpenedWithPlugin(profile, file_path.Extension())) {
    // Use external file URL if it is provided for the file system.
    GURL page_url = chromeos::FileSystemURLToExternalFileURL(file_system_url);
    if (page_url.is_empty())
      page_url = net::FilePathToFileURL(file_path);

    OpenNewTab(profile, page_url);
    return true;
  }

  if (drive::util::HasHostedDocumentExtension(file_path)) {
    if (file_manager::util::IsUnderNonNativeLocalPath(profile, file_path)) {
      // The file is on a non-native volume. Use external file URL. If the file
      // is on the drive volume, ExternalFileURLRequestJob redirects the URL to
      // drive's web interface. Otherwise (e.g. MTP, FSP), the file is just
      // downloaded in a browser tab.
      const GURL url =
          chromeos::FileSystemURLToExternalFileURL(file_system_url);
      DCHECK(!url.is_empty());
      OpenNewTab(profile, url);
    } else {
      // The file is local (downloaded from an attachment or otherwise copied).
      // Parse the file to extract the Docs url and open this url.
      base::PostTaskAndReplyWithResult(
          BrowserThread::GetBlockingPool(),
          FROM_HERE,
          base::Bind(&ReadUrlFromGDocOnBlockingPool, file_path),
          base::Bind(&OpenNewTab, profile));
    }
    return true;
  }

  // Failed to open the file of unknown type.
  LOG(WARNING) << "Unknown file type: " << file_path.value();
  return false;
}

// If a bundled plugin is enabled, we should open pdf/swf files in a tab.
bool ShouldBeOpenedWithPlugin(
    Profile* profile,
    const base::FilePath::StringType& file_extension) {
  DCHECK(profile);

  const base::FilePath file_path =
      base::FilePath::FromUTF8Unsafe("dummy").AddExtension(file_extension);
  if (file_path.MatchesExtension(kPdfExtension))
    return IsPdfPluginEnabled(profile);
  if (file_path.MatchesExtension(kSwfExtension))
    return IsFlashPluginEnabled(profile);
  return false;
}

}  // namespace util
}  // namespace file_manager