Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(108)

Side by Side Diff: chrome/browser/chromeos/extensions/file_manager_util.cc

Issue 13779002: chromeos: Add a subdirectory "file_manager" to chrome/browser/chromeos/extensions (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 #include "chrome/browser/chromeos/extensions/file_manager_util.h"
5
6 #include "ash/shell.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/file_util.h"
10 #include "base/json/json_reader.h"
11 #include "base/json/json_writer.h"
12 #include "base/logging.h"
13 #include "base/metrics/histogram.h"
14 #include "base/path_service.h"
15 #include "base/string_util.h"
16 #include "base/utf_string_conversions.h"
17 #include "base/values.h"
18 #include "chrome/browser/chromeos/drive/drive.pb.h"
19 #include "chrome/browser/chromeos/drive/drive_file_system.h"
20 #include "chrome/browser/chromeos/drive/drive_file_system_util.h"
21 #include "chrome/browser/chromeos/drive/drive_system_service.h"
22 #include "chrome/browser/chromeos/extensions/file_browser_handler.h"
23 #include "chrome/browser/chromeos/extensions/file_handler_util.h"
24 #include "chrome/browser/chromeos/media/media_player.h"
25 #include "chrome/browser/extensions/crx_installer.h"
26 #include "chrome/browser/extensions/extension_install_prompt.h"
27 #include "chrome/browser/extensions/extension_service.h"
28 #include "chrome/browser/extensions/extension_system.h"
29 #include "chrome/browser/google_apis/task_util.h"
30 #include "chrome/browser/plugins/plugin_prefs.h"
31 #include "chrome/browser/profiles/profile.h"
32 #include "chrome/browser/profiles/profile_manager.h"
33 #include "chrome/browser/ui/browser.h"
34 #include "chrome/browser/ui/browser_finder.h"
35 #include "chrome/browser/ui/browser_iterator.h"
36 #include "chrome/browser/ui/browser_tabstrip.h"
37 #include "chrome/browser/ui/browser_window.h"
38 #include "chrome/browser/ui/extensions/application_launch.h"
39 #include "chrome/browser/ui/host_desktop.h"
40 #include "chrome/browser/ui/simple_message_box.h"
41 #include "chrome/browser/ui/tabs/tab_strip_model.h"
42 #include "chrome/common/chrome_paths.h"
43 #include "chrome/common/chrome_switches.h"
44 #include "chrome/common/url_constants.h"
45 #include "content/public/browser/browser_thread.h"
46 #include "content/public/browser/plugin_service.h"
47 #include "content/public/browser/storage_partition.h"
48 #include "content/public/browser/user_metrics.h"
49 #include "content/public/browser/web_contents.h"
50 #include "content/public/common/pepper_plugin_info.h"
51 #include "grit/generated_resources.h"
52 #include "net/base/escape.h"
53 #include "net/base/net_util.h"
54 #include "ui/base/l10n/l10n_util.h"
55 #include "ui/gfx/screen.h"
56 #include "webkit/fileapi/file_system_context.h"
57 #include "webkit/fileapi/file_system_mount_point_provider.h"
58 #include "webkit/fileapi/file_system_operation.h"
59 #include "webkit/fileapi/file_system_url.h"
60 #include "webkit/fileapi/file_system_util.h"
61 #include "webkit/plugins/webplugininfo.h"
62
63 using base::DictionaryValue;
64 using base::ListValue;
65 using content::BrowserContext;
66 using content::BrowserThread;
67 using content::PluginService;
68 using content::UserMetricsAction;
69 using extensions::Extension;
70 using file_handler_util::FileTaskExecutor;
71 using fileapi::FileSystemURL;
72
73 #define FILEBROWSER_EXTENSON_ID "hhaomjibdihmijegdhdafkllkbggdgoj"
74 const char kFileBrowserDomain[] = FILEBROWSER_EXTENSON_ID;
75
76 const char kFileBrowserGalleryTaskId[] = "gallery";
77 const char kFileBrowserMountArchiveTaskId[] = "mount-archive";
78 const char kFileBrowserWatchTaskId[] = "watch";
79 const char kFileBrowserPlayTaskId[] = "play";
80
81 const char kVideoPlayerAppName[] = "videoplayer";
82
83 namespace file_manager_util {
84 namespace {
85
86 #define FILEBROWSER_URL(PATH) \
87 ("chrome-extension://" FILEBROWSER_EXTENSON_ID "/" PATH)
88 // This is the "well known" url for the file manager extension from
89 // browser/resources/file_manager. In the future we may provide a way to swap
90 // out this file manager for an aftermarket part, but not yet.
91 const char kFileBrowserExtensionUrl[] = FILEBROWSER_URL("");
92 const char kBaseFileBrowserUrl[] = FILEBROWSER_URL("main.html");
93 const char kMediaPlayerUrl[] = FILEBROWSER_URL("mediaplayer.html");
94 const char kVideoPlayerUrl[] = FILEBROWSER_URL("video_player.html");
95 const char kActionChoiceUrl[] = FILEBROWSER_URL("action_choice.html");
96 #undef FILEBROWSER_URL
97 #undef FILEBROWSER_EXTENSON_ID
98
99 const char kCRXExtension[] = ".crx";
100 const char kPdfExtension[] = ".pdf";
101 const char kSwfExtension[] = ".swf";
102 // List of file extension we can open in tab.
103 const char* kBrowserSupportedExtensions[] = {
104 #if defined(GOOGLE_CHROME_BUILD)
105 ".pdf", ".swf",
106 #endif
107 ".bmp", ".jpg", ".jpeg", ".png", ".webp", ".gif", ".txt", ".html", ".htm",
108 ".mhtml", ".mht", ".svg"
109 };
110
111 // Keep in sync with 'open-hosted' task handler in the File Browser manifest.
112 const char* kGDocsExtensions[] = {
113 ".gdoc", ".gsheet", ".gslides", ".gdraw", ".gtable", ".glink"
114 };
115
116 // List of all extensions we want to be shown in histogram that keep track of
117 // files that were unsuccessfully tried to be opened.
118 // The list has to be synced with histogram values.
119 const char* kUMATrackingExtensions[] = {
120 "other", ".doc", ".docx", ".odt", ".rtf", ".pdf", ".ppt", ".pptx", ".odp",
121 ".xls", ".xlsx", ".ods", ".csv", ".odf", ".rar", ".asf", ".wma", ".wmv",
122 ".mov", ".mpg", ".log"
123 };
124
125 bool IsSupportedBrowserExtension(const char* file_extension) {
126 for (size_t i = 0; i < arraysize(kBrowserSupportedExtensions); i++) {
127 if (base::strcasecmp(file_extension, kBrowserSupportedExtensions[i]) == 0) {
128 return true;
129 }
130 }
131 return false;
132 }
133
134 bool IsSupportedGDocsExtension(const char* file_extension) {
135 for (size_t i = 0; i < arraysize(kGDocsExtensions); i++) {
136 if (base::strcasecmp(file_extension, kGDocsExtensions[i]) == 0) {
137 return true;
138 }
139 }
140 return false;
141 }
142
143 bool IsCRXFile(const char* file_extension) {
144 return base::strcasecmp(file_extension, kCRXExtension) == 0;
145 }
146
147 bool IsPepperPluginEnabled(Profile* profile,
148 const base::FilePath& plugin_path) {
149 content::PepperPluginInfo* pepper_info =
150 PluginService::GetInstance()->GetRegisteredPpapiPluginInfo(plugin_path);
151 if (!pepper_info)
152 return false;
153
154 PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(profile);
155 if (!plugin_prefs)
156 return false;
157
158 return plugin_prefs->IsPluginEnabled(pepper_info->ToWebPluginInfo());
159 }
160
161 bool IsPdfPluginEnabled(Profile* profile) {
162 base::FilePath plugin_path;
163 PathService::Get(chrome::FILE_PDF_PLUGIN, &plugin_path);
164 return IsPepperPluginEnabled(profile, plugin_path);
165 }
166
167 bool IsFlashPluginEnabled(Profile* profile) {
168 base::FilePath plugin_path(
169 CommandLine::ForCurrentProcess()->GetSwitchValueNative(
170 switches::kPpapiFlashPath));
171 if (plugin_path.empty())
172 PathService::Get(chrome::FILE_PEPPER_FLASH_PLUGIN, &plugin_path);
173 return IsPepperPluginEnabled(profile, plugin_path);
174 }
175
176 // Returns index |ext| has in the |array|. If there is no |ext| in |array|, last
177 // element's index is return (last element should have irrelevant value).
178 int UMAExtensionIndex(const char *file_extension,
179 const char** array,
180 size_t array_size) {
181 for (size_t i = 0; i < array_size; i++) {
182 if (base::strcasecmp(file_extension, array[i]) == 0) {
183 return i;
184 }
185 }
186 return 0;
187 }
188
189 // Convert numeric dialog type to a string.
190 std::string GetDialogTypeAsString(
191 ui::SelectFileDialog::Type dialog_type) {
192 std::string type_str;
193 switch (dialog_type) {
194 case ui::SelectFileDialog::SELECT_NONE:
195 type_str = "full-page";
196 break;
197
198 case ui::SelectFileDialog::SELECT_FOLDER:
199 type_str = "folder";
200 break;
201
202 case ui::SelectFileDialog::SELECT_SAVEAS_FILE:
203 type_str = "saveas-file";
204 break;
205
206 case ui::SelectFileDialog::SELECT_OPEN_FILE:
207 type_str = "open-file";
208 break;
209
210 case ui::SelectFileDialog::SELECT_OPEN_MULTI_FILE:
211 type_str = "open-multi-file";
212 break;
213
214 default:
215 NOTREACHED();
216 }
217
218 return type_str;
219 }
220
221 DictionaryValue* ProgessStatusToDictionaryValue(
222 Profile* profile,
223 const std::string& extension_id,
224 const google_apis::OperationProgressStatus& status) {
225 scoped_ptr<DictionaryValue> result(new DictionaryValue());
226 GURL file_url;
227 if (file_manager_util::ConvertFileToFileSystemUrl(profile,
228 drive::util::GetSpecialRemoteRootPath().Append(
229 base::FilePath(status.file_path)),
230 extension_id,
231 &file_url)) {
232 result->SetString("fileUrl", file_url.spec());
233 }
234
235 result->SetString("transferState",
236 OperationTransferStateToString(status.transfer_state));
237 result->SetString("transferType",
238 OperationTypeToString(status.operation_type));
239 result->SetInteger("processed", static_cast<int>(status.progress_current));
240 result->SetInteger("total", static_cast<int>(status.progress_total));
241 return result.release();
242 }
243
244 void OpenNewTab(const GURL& url, Profile* profile) {
245 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
246 Browser* browser = chrome::FindOrCreateTabbedBrowser(
247 profile ? profile : ProfileManager::GetDefaultProfileOrOffTheRecord(),
248 chrome::HOST_DESKTOP_TYPE_ASH);
249 chrome::AddSelectedTabWithURL(browser, url, content::PAGE_TRANSITION_LINK);
250 // If the current browser is not tabbed then the new tab will be created
251 // in a different browser. Make sure it is visible.
252 browser->window()->Show();
253 }
254
255 // Shows a warning message box saying that the file could not be opened.
256 void ShowWarningMessageBox(Profile* profile, const base::FilePath& path) {
257 // TODO: if FindOrCreateTabbedBrowser creates a new browser the returned
258 // browser is leaked.
259 Browser* browser =
260 chrome::FindOrCreateTabbedBrowser(profile,
261 chrome::HOST_DESKTOP_TYPE_ASH);
262 chrome::ShowMessageBox(
263 browser->window()->GetNativeWindow(),
264 l10n_util::GetStringFUTF16(
265 IDS_FILE_BROWSER_ERROR_VIEWING_FILE_TITLE,
266 UTF8ToUTF16(path.BaseName().value())),
267 l10n_util::GetStringUTF16(IDS_FILE_BROWSER_ERROR_VIEWING_FILE),
268 chrome::MESSAGE_BOX_TYPE_WARNING);
269 }
270
271 // Called when a file on Drive was found. Opens the file found at |file_path|
272 // in a new tab with a URL computed based on the |file_type|
273 void OnDriveFileFound(Profile* profile,
274 const base::FilePath& file_path,
275 drive::DriveFileType file_type,
276 drive::DriveFileError error,
277 scoped_ptr<drive::DriveEntryProto> entry_proto) {
278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
279
280 if (entry_proto.get() && !entry_proto->has_file_specific_info())
281 error = drive::DRIVE_FILE_ERROR_NOT_FOUND;
282
283 if (error == drive::DRIVE_FILE_OK) {
284 GURL page_url;
285 if (file_type == drive::REGULAR_FILE) {
286 page_url = drive::util::FilePathToDriveURL(
287 drive::util::ExtractDrivePath(file_path));
288 } else if (file_type == drive::HOSTED_DOCUMENT) {
289 page_url = GURL(entry_proto->file_specific_info().alternate_url());
290 } else {
291 NOTREACHED();
292 }
293 OpenNewTab(page_url, profile);
294 } else {
295 ShowWarningMessageBox(profile, file_path);
296 }
297 }
298
299 void InstallCRX(Browser* browser, const base::FilePath& path) {
300 ExtensionService* service =
301 extensions::ExtensionSystem::Get(browser->profile())->extension_service();
302 CHECK(service);
303
304 content::WebContents* web_contents =
305 browser->tab_strip_model()->GetActiveWebContents();
306 scoped_refptr<extensions::CrxInstaller> installer(
307 extensions::CrxInstaller::Create(
308 service,
309 new ExtensionInstallPrompt(web_contents)));
310 installer->set_error_on_unsupported_requirements(true);
311 installer->set_is_gallery_install(false);
312 installer->set_allow_silent_install(false);
313 installer->InstallCrx(path);
314 }
315
316 // Called when a crx file on Drive was downloaded.
317 void OnCRXDownloadCallback(Browser* browser,
318 drive::DriveFileError error,
319 const base::FilePath& file,
320 const std::string& unused_mime_type,
321 drive::DriveFileType file_type) {
322 if (error != drive::DRIVE_FILE_OK || file_type != drive::REGULAR_FILE)
323 return;
324 InstallCRX(browser, file);
325 }
326
327 enum TAB_REUSE_MODE {
328 REUSE_ANY_FILE_MANAGER,
329 REUSE_SAME_PATH,
330 REUSE_NEVER
331 };
332
333 bool FileManageTabExists(const base::FilePath& path, TAB_REUSE_MODE mode) {
334 if (mode == REUSE_NEVER)
335 return false;
336
337 // We always open full-tab File Manager via chrome://files URL, never
338 // chrome-extension://, so we only check against chrome://files
339 const GURL origin(chrome::kChromeUIFileManagerURL);
340 const std::string ref = std::string("/") + path.value();
341
342 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
343 Browser* browser = *it;
344 TabStripModel* tab_strip = browser->tab_strip_model();
345 for (int idx = 0; idx < tab_strip->count(); idx++) {
346 content::WebContents* web_contents = tab_strip->GetWebContentsAt(idx);
347 const GURL& url = web_contents->GetURL();
348 if (origin == url.GetOrigin()) {
349 if (mode == REUSE_ANY_FILE_MANAGER || ref == url.ref()) {
350 if (mode == REUSE_SAME_PATH && tab_strip->active_index() != idx) {
351 browser->window()->Show();
352 tab_strip->ActivateTabAt(idx, false);
353 }
354 return true;
355 }
356 }
357 }
358 }
359
360 return false;
361 }
362
363 bool IsFileManagerPackaged() {
364 const CommandLine* command_line = CommandLine::ForCurrentProcess();
365 return command_line->HasSwitch(switches::kFileManagerPackaged);
366 }
367
368 // Grants file system access to the file browser.
369 bool GrantFileSystemAccessToFileBrowser(Profile* profile) {
370 // File browser always runs in the site for its extension id, so that is the
371 // site for which file access permissions should be granted.
372 GURL site = extensions::ExtensionSystem::Get(profile)->extension_service()->
373 GetSiteForExtensionId(kFileBrowserDomain);
374 fileapi::ExternalFileSystemMountPointProvider* external_provider =
375 BrowserContext::GetStoragePartitionForSite(profile, site)->
376 GetFileSystemContext()->external_provider();
377 if (!external_provider)
378 return false;
379 GURL url(kBaseFileBrowserUrl);
380 external_provider->GrantFullAccessToExtension(url.host());
381 return true;
382 }
383
384 // Executes handler specifed with |extension_id| and |action_id| for |url|.
385 void ExecuteHandler(Profile* profile,
386 std::string extension_id,
387 std::string action_id,
388 const GURL& url) {
389 // If File Browser has not been open yet then it did not request access
390 // to the file system. Do it now.
391 if (!GrantFileSystemAccessToFileBrowser(profile))
392 return;
393
394 GURL site = extensions::ExtensionSystem::Get(profile)->extension_service()->
395 GetSiteForExtensionId(kFileBrowserDomain);
396 fileapi::FileSystemContext* file_system_context =
397 BrowserContext::GetStoragePartitionForSite(profile, site)->
398 GetFileSystemContext();
399
400 // We are executing the task on behalf of File Browser extension.
401 const GURL source_url(kBaseFileBrowserUrl);
402 std::vector<FileSystemURL> urls;
403 urls.push_back(file_system_context->CrackURL(url));
404 scoped_refptr<FileTaskExecutor> executor = FileTaskExecutor::Create(profile,
405 source_url, kFileBrowserDomain, 0 /* no tab id */, extension_id,
406 file_handler_util::kTaskFile, action_id);
407 executor->Execute(urls);
408 }
409
410 void OpenFileBrowserImpl(const base::FilePath& path,
411 TAB_REUSE_MODE mode,
412 const std::string& action_id) {
413 content::RecordAction(UserMetricsAction("ShowFileBrowserFullTab"));
414
415 if (FileManageTabExists(path, mode))
416 return;
417
418 Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord();
419
420 if (IsFileManagerPackaged() && !path.value().empty()) {
421 GURL url;
422 if (!ConvertFileToFileSystemUrl(profile, path, kFileBrowserDomain, &url))
423 return;
424
425 // Some values of |action_id| are not listed in the manifest and are used
426 // to parametrize the behavior when opening the Files app window.
427 ExecuteHandler(profile, kFileBrowserDomain, action_id, url);
428 return;
429 }
430
431 std::string url = chrome::kChromeUIFileManagerURL;
432 if (action_id.size()) {
433 DictionaryValue arg_value;
434 arg_value.SetString("action", action_id);
435 std::string query;
436 base::JSONWriter::Write(&arg_value, &query);
437 url += "?" +
438 net::EscapeUrlEncodedData(query,
439 false); // Space to %20 instead of +.
440 }
441 if (!path.empty()) {
442 base::FilePath virtual_path;
443 if (!ConvertFileToRelativeFileSystemPath(profile, kFileBrowserDomain, path,
444 &virtual_path))
445 return;
446 url += "#/" +
447 net::EscapeUrlEncodedData(virtual_path.value(),
448 false); // Space to %20 instead of +.
449 }
450
451 ExtensionService* service =
452 extensions::ExtensionSystem::Get(profile)->extension_service();
453 if (!service)
454 return;
455
456 const extensions::Extension* extension =
457 service->GetExtensionById(kFileBrowserDomain, false);
458 if (!extension)
459 return;
460
461 chrome::AppLaunchParams params(profile, extension,
462 extension_misc::LAUNCH_WINDOW,
463 NEW_FOREGROUND_TAB);
464 params.override_url = GURL(url);
465 chrome::OpenApplication(params);
466 }
467
468 Browser* GetBrowserForUrl(GURL target_url) {
469 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
470 Browser* browser = *it;
471 TabStripModel* tab_strip = browser->tab_strip_model();
472 for (int idx = 0; idx < tab_strip->count(); idx++) {
473 content::WebContents* web_contents = tab_strip->GetWebContentsAt(idx);
474 const GURL& url = web_contents->GetURL();
475 if (url == target_url)
476 return browser;
477 }
478 }
479 return NULL;
480 }
481
482 bool ExecuteDefaultHandler(Profile* profile, const base::FilePath& path) {
483 GURL url;
484 if (!ConvertFileToFileSystemUrl(profile, path, kFileBrowserDomain, &url))
485 return false;
486
487 const FileBrowserHandler* handler;
488 if (!file_handler_util::GetTaskForURLAndPath(profile, url, path, &handler))
489 return false;
490
491 std::string extension_id = handler->extension_id();
492 std::string action_id = handler->id();
493 Browser* browser = chrome::FindLastActiveWithProfile(profile,
494 chrome::HOST_DESKTOP_TYPE_ASH);
495
496 // If there is no browsers for the profile, bail out. Return true so warning
497 // about file type not being supported is not displayed.
498 if (!browser)
499 return true;
500
501 if (extension_id == kFileBrowserDomain) {
502 if (IsFileManagerPackaged()) {
503 if (action_id == kFileBrowserGalleryTaskId ||
504 action_id == kFileBrowserMountArchiveTaskId ||
505 action_id == kFileBrowserPlayTaskId ||
506 action_id == kFileBrowserWatchTaskId) {
507 ExecuteHandler(profile, extension_id, action_id, url);
508 return true;
509 }
510 return ExecuteBuiltinHandler(browser, path, action_id);
511 }
512
513 // Only two of the built-in File Browser tasks require opening the File
514 // Browser tab.
515 if (action_id == kFileBrowserGalleryTaskId ||
516 action_id == kFileBrowserMountArchiveTaskId) {
517 // Tab reuse currently does not work for these two tasks.
518 // |gallery| tries to put the file url into the tab url but it does not
519 // work on Chrome OS.
520 // |mount-archive| does not even try.
521 OpenFileBrowserImpl(path, REUSE_SAME_PATH, "");
522 return true;
523 }
524 return ExecuteBuiltinHandler(browser, path, action_id);
525 }
526
527 ExecuteHandler(profile, extension_id, action_id, url);
528 return true;
529 }
530
531 // Reads an entire file into a string. Fails is the file is 4K or longer.
532 bool ReadSmallFileToString(const base::FilePath& path, std::string* contents) {
533 FILE* file = file_util::OpenFile(path, "rb");
534 if (!file) {
535 return false;
536 }
537
538 char buf[1 << 12]; // 4K
539 size_t len = fread(buf, 1, sizeof(buf), file);
540 if (len > 0) {
541 contents->append(buf, len);
542 }
543 file_util::CloseFile(file);
544
545 return len < sizeof(buf);
546 }
547
548 // Reads JSON from a Google Docs file, extracts a document url and opens it
549 // in a tab.
550 void ReadUrlFromGDocOnBlockingPool(const base::FilePath& file_path) {
551 std::string contents;
552 if (!ReadSmallFileToString(file_path, &contents)) {
553 LOG(ERROR) << "Error reading " << file_path.value();
554 return;
555 }
556
557 scoped_ptr<base::Value> root_value;
558 root_value.reset(base::JSONReader::Read(contents));
559
560 DictionaryValue* dictionary_value;
561 std::string edit_url_string;
562 if (!root_value.get() ||
563 !root_value->GetAsDictionary(&dictionary_value) ||
564 !dictionary_value->GetString("url", &edit_url_string)) {
565 LOG(ERROR) << "Invalid JSON in " << file_path.value();
566 return;
567 }
568
569 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
570 base::Bind(OpenNewTab, GURL(edit_url_string), (Profile*)NULL));
571 }
572
573 // Used to implement ViewItem().
574 void ContinueViewItem(Profile* profile,
575 const base::FilePath& path,
576 base::PlatformFileError error) {
577 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
578
579 if (error == base::PLATFORM_FILE_OK) {
580 // A directory exists at |path|. Open it with FileBrowser.
581 OpenFileBrowserImpl(path, REUSE_SAME_PATH, "open");
582 } else {
583 if (!ExecuteDefaultHandler(profile, path))
584 ShowWarningMessageBox(profile, path);
585 }
586 }
587
588 // Used to implement CheckIfDirectoryExists().
589 void CheckIfDirectoryExistsOnIOThread(
590 scoped_refptr<fileapi::FileSystemContext> file_system_context,
591 const GURL& url,
592 const fileapi::FileSystemOperation::StatusCallback& callback) {
593 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
594
595 fileapi::FileSystemURL file_system_url = file_system_context->CrackURL(url);
596 base::PlatformFileError error = base::PLATFORM_FILE_OK;
597 fileapi::FileSystemOperation* operation =
598 file_system_context->CreateFileSystemOperation(file_system_url, &error);
599 if (error != base::PLATFORM_FILE_OK) {
600 callback.Run(error);
601 return;
602 }
603 operation->DirectoryExists(file_system_url, callback);
604 }
605
606 // Checks if a directory exists at |url|.
607 void CheckIfDirectoryExists(
608 scoped_refptr<fileapi::FileSystemContext> file_system_context,
609 const GURL& url,
610 const fileapi::FileSystemOperation::StatusCallback& callback) {
611 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
612
613 BrowserThread::PostTask(
614 BrowserThread::IO, FROM_HERE,
615 base::Bind(&CheckIfDirectoryExistsOnIOThread,
616 file_system_context,
617 url,
618 google_apis::CreateRelayCallback(callback)));
619 }
620
621 } // namespace
622
623 GURL GetFileBrowserExtensionUrl() {
624 return GURL(kFileBrowserExtensionUrl);
625 }
626
627 GURL GetFileBrowserUrl() {
628 return GURL(kBaseFileBrowserUrl);
629 }
630
631 GURL GetMediaPlayerUrl() {
632 return GURL(kMediaPlayerUrl);
633 }
634
635 GURL GetVideoPlayerUrl(const GURL& source_url) {
636 return GURL(kVideoPlayerUrl + std::string("?") + source_url.spec());
637 }
638
639 bool ConvertFileToFileSystemUrl(Profile* profile,
640 const base::FilePath& full_file_path,
641 const std::string& extension_id,
642 GURL* url) {
643 GURL origin_url = Extension::GetBaseURLFromExtensionId(extension_id);
644 base::FilePath virtual_path;
645 if (!ConvertFileToRelativeFileSystemPath(profile, extension_id,
646 full_file_path, &virtual_path)) {
647 return false;
648 }
649
650 GURL base_url = fileapi::GetFileSystemRootURI(origin_url,
651 fileapi::kFileSystemTypeExternal);
652 *url = GURL(base_url.spec() +
653 net::EscapeUrlEncodedData(virtual_path.value(),
654 false)); // Space to %20 instead of +.
655 return true;
656 }
657
658 bool ConvertFileToRelativeFileSystemPath(
659 Profile* profile,
660 const std::string& extension_id,
661 const base::FilePath& full_file_path,
662 base::FilePath* virtual_path) {
663 ExtensionService* service =
664 extensions::ExtensionSystem::Get(profile)->extension_service();
665 // May be NULL during unit_tests.
666 if (!service)
667 return false;
668
669 // File browser APIs are ment to be used only from extension context, so the
670 // extension's site is the one in whose file system context the virtual path
671 // should be found.
672 GURL site = service->GetSiteForExtensionId(extension_id);
673 fileapi::ExternalFileSystemMountPointProvider* provider =
674 BrowserContext::GetStoragePartitionForSite(profile, site)->
675 GetFileSystemContext()->external_provider();
676 if (!provider)
677 return false;
678
679 // Find if this file path is managed by the external provider.
680 if (!provider->GetVirtualPath(full_file_path, virtual_path))
681 return false;
682
683 return true;
684 }
685
686 GURL GetFileBrowserUrlWithParams(
687 ui::SelectFileDialog::Type type,
688 const string16& title,
689 const base::FilePath& default_virtual_path,
690 const ui::SelectFileDialog::FileTypeInfo* file_types,
691 int file_type_index,
692 const base::FilePath::StringType& default_extension) {
693 DictionaryValue arg_value;
694 arg_value.SetString("type", GetDialogTypeAsString(type));
695 arg_value.SetString("title", title);
696 arg_value.SetString("defaultPath", default_virtual_path.value());
697 arg_value.SetString("defaultExtension", default_extension);
698
699 if (file_types) {
700 ListValue* types_list = new ListValue();
701 for (size_t i = 0; i < file_types->extensions.size(); ++i) {
702 ListValue* extensions_list = new ListValue();
703 for (size_t j = 0; j < file_types->extensions[i].size(); ++j) {
704 extensions_list->Append(
705 new base::StringValue(file_types->extensions[i][j]));
706 }
707
708 DictionaryValue* dict = new DictionaryValue();
709 dict->Set("extensions", extensions_list);
710
711 if (i < file_types->extension_description_overrides.size()) {
712 string16 desc = file_types->extension_description_overrides[i];
713 dict->SetString("description", desc);
714 }
715
716 // file_type_index is 1-based. 0 means no selection at all.
717 dict->SetBoolean("selected",
718 (static_cast<size_t>(file_type_index) == (i + 1)));
719
720 types_list->Set(i, dict);
721 }
722 arg_value.Set("typeList", types_list);
723
724 arg_value.SetBoolean("includeAllFiles", file_types->include_all_files);
725 }
726
727 // If the caller cannot handle Drive path, the file chooser dialog need to
728 // return resolved local native paths to the selected files.
729 arg_value.SetBoolean("shouldReturnLocalPath",
730 !file_types || !file_types->support_drive);
731
732 std::string json_args;
733 base::JSONWriter::Write(&arg_value, &json_args);
734
735 // kChromeUIFileManagerURL could not be used since query parameters are not
736 // supported for it.
737 std::string url = GetFileBrowserUrl().spec() + '?' +
738 net::EscapeUrlEncodedData(json_args,
739 false); // Space to %20 instead of +.
740 return GURL(url);
741 }
742
743 string16 GetTitleFromType(ui::SelectFileDialog::Type dialog_type) {
744 string16 title;
745 switch (dialog_type) {
746 case ui::SelectFileDialog::SELECT_NONE:
747 // Full page file manager doesn't need a title.
748 break;
749
750 case ui::SelectFileDialog::SELECT_FOLDER:
751 title = l10n_util::GetStringUTF16(
752 IDS_FILE_BROWSER_SELECT_FOLDER_TITLE);
753 break;
754
755 case ui::SelectFileDialog::SELECT_SAVEAS_FILE:
756 title = l10n_util::GetStringUTF16(
757 IDS_FILE_BROWSER_SELECT_SAVEAS_FILE_TITLE);
758 break;
759
760 case ui::SelectFileDialog::SELECT_OPEN_FILE:
761 title = l10n_util::GetStringUTF16(
762 IDS_FILE_BROWSER_SELECT_OPEN_FILE_TITLE);
763 break;
764
765 case ui::SelectFileDialog::SELECT_OPEN_MULTI_FILE:
766 title = l10n_util::GetStringUTF16(
767 IDS_FILE_BROWSER_SELECT_OPEN_MULTI_FILE_TITLE);
768 break;
769
770 default:
771 NOTREACHED();
772 }
773
774 return title;
775 }
776
777 void ViewRemovableDrive(const base::FilePath& path) {
778 OpenFileBrowserImpl(path, REUSE_ANY_FILE_MANAGER, "auto-open");
779 }
780
781 void OpenNewWindow(Profile* profile, const GURL& url) {
782 ExtensionService* service = extensions::ExtensionSystem::Get(
783 profile ? profile : ProfileManager::GetDefaultProfileOrOffTheRecord())->
784 extension_service();
785 if (!service)
786 return;
787
788 const extensions::Extension* extension =
789 service->GetExtensionById(kFileBrowserDomain, false);
790 if (!extension)
791 return;
792
793 chrome::AppLaunchParams params(profile, extension,
794 extension_misc::LAUNCH_WINDOW,
795 NEW_FOREGROUND_TAB);
796 params.override_url = url;
797 chrome::OpenApplication(params);
798 }
799
800 void OpenActionChoiceDialog(const base::FilePath& path, bool advanced_mode) {
801 const int kDialogWidth = 394;
802 // TODO(dgozman): remove 50, which is a title height once popup window
803 // will have no title.
804 const int kDialogHeight = 316 + 50;
805
806 Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord();
807
808 base::FilePath virtual_path;
809 if (!ConvertFileToRelativeFileSystemPath(profile, kFileBrowserDomain, path,
810 &virtual_path))
811 return;
812 std::string url = kActionChoiceUrl;
813 if (advanced_mode)
814 url += "?advanced-mode";
815 url += "#/" + net::EscapeUrlEncodedData(virtual_path.value(),
816 false); // Space to %20 instead of +.
817 GURL dialog_url(url);
818
819 const gfx::Size screen = ash::Shell::GetScreen()->GetPrimaryDisplay().size();
820 const gfx::Rect bounds((screen.width() - kDialogWidth) / 2,
821 (screen.height() - kDialogHeight) / 2,
822 kDialogWidth,
823 kDialogHeight);
824
825 Browser* browser = GetBrowserForUrl(dialog_url);
826
827 if (browser) {
828 browser->window()->Show();
829 return;
830 }
831
832 ExtensionService* service = extensions::ExtensionSystem::Get(
833 profile ? profile : ProfileManager::GetDefaultProfileOrOffTheRecord())->
834 extension_service();
835 if (!service)
836 return;
837
838 const extensions::Extension* extension =
839 service->GetExtensionById(kFileBrowserDomain, false);
840 if (!extension)
841 return;
842
843 chrome::AppLaunchParams params(profile, extension,
844 extension_misc::LAUNCH_WINDOW,
845 NEW_FOREGROUND_TAB);
846 params.override_url = dialog_url;
847 params.override_bounds = bounds;
848 chrome::OpenApplication(params);
849 }
850
851 void ViewItem(const base::FilePath& path) {
852 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
853
854 Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord();
855 GURL url;
856 if (!ConvertFileToFileSystemUrl(profile, path, kFileBrowserDomain, &url) ||
857 !GrantFileSystemAccessToFileBrowser(profile)) {
858 ShowWarningMessageBox(profile, path);
859 return;
860 }
861
862 GURL site = extensions::ExtensionSystem::Get(profile)->extension_service()->
863 GetSiteForExtensionId(kFileBrowserDomain);
864 scoped_refptr<fileapi::FileSystemContext> file_system_context =
865 BrowserContext::GetStoragePartitionForSite(profile, site)->
866 GetFileSystemContext();
867
868 CheckIfDirectoryExists(file_system_context, url,
869 base::Bind(&ContinueViewItem, profile, path));
870 }
871
872 void ShowFileInFolder(const base::FilePath& path) {
873 // This action changes the selection so we do not reuse existing tabs.
874 OpenFileBrowserImpl(path, REUSE_NEVER, "select");
875 }
876
877 void OpenFileBrowser() {
878 OpenFileBrowserImpl(base::FilePath(), REUSE_NEVER, "");
879 }
880
881 bool ExecuteBuiltinHandler(Browser* browser, const base::FilePath& path,
882 const std::string& internal_task_id) {
883
884 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
885
886 Profile* profile = browser->profile();
887 std::string file_extension = path.Extension();
888 // For things supported natively by the browser, we should open it
889 // in a tab.
890 if (IsSupportedBrowserExtension(file_extension.data()) ||
891 ShouldBeOpenedWithPlugin(profile, file_extension.data())) {
892 GURL page_url = net::FilePathToFileURL(path);
893 // Override gdata resource to point to internal handler instead of file:
894 // URL.
895 if (drive::util::GetSpecialRemoteRootPath().IsParent(path)) {
896 drive::DriveSystemService* system_service =
897 drive::DriveSystemServiceFactory::GetForProfile(profile);
898 if (!system_service)
899 return false;
900
901 // Open the file once the file is found.
902 system_service->file_system()->GetEntryInfoByPath(
903 drive::util::ExtractDrivePath(path),
904 base::Bind(&OnDriveFileFound, profile, path, drive::REGULAR_FILE));
905 return true;
906 }
907 OpenNewTab(page_url, NULL);
908 return true;
909 }
910
911 if (IsSupportedGDocsExtension(file_extension.data())) {
912 if (drive::util::GetSpecialRemoteRootPath().IsParent(path)) {
913 // The file is on Google Docs. Get the Docs from the Drive service.
914 drive::DriveSystemService* system_service =
915 drive::DriveSystemServiceFactory::GetForProfile(profile);
916 if (!system_service)
917 return false;
918
919 system_service->file_system()->GetEntryInfoByPath(
920 drive::util::ExtractDrivePath(path),
921 base::Bind(&OnDriveFileFound, profile, path,
922 drive::HOSTED_DOCUMENT));
923 } else {
924 // The file is local (downloaded from an attachment or otherwise copied).
925 // Parse the file to extract the Docs url and open this url.
926 BrowserThread::PostBlockingPoolTask(
927 FROM_HERE, base::Bind(&ReadUrlFromGDocOnBlockingPool, path));
928 }
929 return true;
930 }
931
932 if (!IsFileManagerPackaged()) {
933 if (internal_task_id == kFileBrowserPlayTaskId) {
934 GURL url;
935 if (!ConvertFileToFileSystemUrl(profile, path, kFileBrowserDomain, &url))
936 return false;
937 MediaPlayer* mediaplayer = MediaPlayer::GetInstance();
938 mediaplayer->PopupMediaPlayer();
939 mediaplayer->ForcePlayMediaURL(url);
940 return true;
941 }
942 if (internal_task_id == kFileBrowserWatchTaskId) {
943 GURL url;
944 if (!ConvertFileToFileSystemUrl(profile, path, kFileBrowserDomain, &url))
945 return false;
946
947 ExtensionService* service =
948 extensions::ExtensionSystem::Get(profile)->extension_service();
949 if (!service)
950 return false;
951
952 const extensions::Extension* extension =
953 service->GetExtensionById(kFileBrowserDomain, false);
954 if (!extension)
955 return false;
956
957 chrome::AppLaunchParams params(profile, extension,
958 extension_misc::LAUNCH_WINDOW,
959 NEW_FOREGROUND_TAB);
960 params.override_url = GetVideoPlayerUrl(url);
961 chrome::OpenApplication(params);
962 return true;
963 }
964 }
965
966 if (IsCRXFile(file_extension.data())) {
967 if (drive::util::IsUnderDriveMountPoint(path)) {
968 drive::DriveSystemService* system_service =
969 drive::DriveSystemServiceFactory::GetForProfile(profile);
970 if (!system_service)
971 return false;
972 system_service->file_system()->GetFileByPath(
973 drive::util::ExtractDrivePath(path),
974 base::Bind(&OnCRXDownloadCallback, browser));
975 } else {
976 InstallCRX(browser, path);
977 }
978 return true;
979 }
980
981 // Unknown file type. Record UMA and show an error message.
982 size_t extension_index = UMAExtensionIndex(file_extension.data(),
983 kUMATrackingExtensions,
984 arraysize(kUMATrackingExtensions));
985 UMA_HISTOGRAM_ENUMERATION("FileBrowser.OpeningFileType",
986 extension_index,
987 arraysize(kUMATrackingExtensions) - 1);
988 return false;
989 }
990
991 // If a bundled plugin is enabled, we should open pdf/swf files in a tab.
992 bool ShouldBeOpenedWithPlugin(Profile* profile, const char* file_extension) {
993 if (LowerCaseEqualsASCII(file_extension, kPdfExtension))
994 return IsPdfPluginEnabled(profile);
995 if (LowerCaseEqualsASCII(file_extension, kSwfExtension))
996 return IsFlashPluginEnabled(profile);
997 return false;
998 }
999
1000 ListValue* ProgressStatusVectorToListValue(
1001 Profile* profile,
1002 const std::string& extension_id,
1003 const google_apis::OperationProgressStatusList& list) {
1004 scoped_ptr<ListValue> result_list(new ListValue());
1005 for (google_apis::OperationProgressStatusList::const_iterator iter =
1006 list.begin();
1007 iter != list.end(); ++iter) {
1008 result_list->Append(
1009 ProgessStatusToDictionaryValue(profile, extension_id, *iter));
1010 }
1011 return result_list.release();
1012 }
1013
1014 } // namespace file_manager_util
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/extensions/file_manager_util.h ('k') | chrome/browser/chromeos/media/media_player.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698