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

Side by Side Diff: chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.cc

Issue 23945002: file_manager: Move non-binding code to c/b/chromeos/file_manager (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 3 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
5 #include "chrome/browser/chromeos/extensions/file_manager/file_browser_handlers. h"
6
7 #include "base/bind.h"
8 #include "base/file_util.h"
9 #include "base/i18n/case_conversion.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/chromeos/drive/file_system_util.h"
12 #include "chrome/browser/chromeos/extensions/file_manager/app_id.h"
13 #include "chrome/browser/chromeos/extensions/file_manager/fileapi_util.h"
14 #include "chrome/browser/chromeos/extensions/file_manager/open_with_browser.h"
15 #include "chrome/browser/chromeos/fileapi/file_system_backend.h"
16 #include "chrome/browser/extensions/event_router.h"
17 #include "chrome/browser/extensions/extension_host.h"
18 #include "chrome/browser/extensions/extension_service.h"
19 #include "chrome/browser/extensions/extension_system.h"
20 #include "chrome/browser/extensions/lazy_background_task_queue.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/ui/browser_finder.h"
23 #include "chrome/common/extensions/api/file_browser_handlers/file_browser_handle r.h"
24 #include "chrome/common/extensions/background_info.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/child_process_security_policy.h"
27 #include "content/public/browser/render_process_host.h"
28 #include "content/public/browser/site_instance.h"
29 #include "content/public/browser/web_contents.h"
30 #include "net/base/escape.h"
31 #include "webkit/browser/fileapi/file_system_context.h"
32 #include "webkit/browser/fileapi/file_system_url.h"
33
34 using content::BrowserThread;
35 using content::ChildProcessSecurityPolicy;
36 using content::SiteInstance;
37 using content::WebContents;
38 using extensions::Extension;
39 using fileapi::FileSystemURL;
40
41 namespace file_manager {
42 namespace file_browser_handlers {
43 namespace {
44
45 // Returns process id of the process the extension is running in.
46 int ExtractProcessFromExtensionId(Profile* profile,
47 const std::string& extension_id) {
48 GURL extension_url =
49 Extension::GetBaseURLFromExtensionId(extension_id);
50 ExtensionProcessManager* manager =
51 extensions::ExtensionSystem::Get(profile)->process_manager();
52
53 SiteInstance* site_instance = manager->GetSiteInstanceForURL(extension_url);
54 if (!site_instance || !site_instance->HasProcess())
55 return -1;
56 content::RenderProcessHost* process = site_instance->GetProcess();
57
58 return process->GetID();
59 }
60
61 // Finds a file browser handler that matches |action_id|. Returns NULL if not
62 // found.
63 const FileBrowserHandler* FindFileBrowserHandlerForActionId(
64 const Extension* extension,
65 const std::string& action_id) {
66 FileBrowserHandler::List* handler_list =
67 FileBrowserHandler::GetHandlers(extension);
68 for (FileBrowserHandler::List::const_iterator handler_iter =
69 handler_list->begin();
70 handler_iter != handler_list->end();
71 ++handler_iter) {
72 if (handler_iter->get()->id() == action_id)
73 return handler_iter->get();
74 }
75 return NULL;
76 }
77
78 std::string EscapedUtf8ToLower(const std::string& str) {
79 string16 utf16 = UTF8ToUTF16(
80 net::UnescapeURLComponent(str, net::UnescapeRule::NORMAL));
81 return net::EscapeUrlEncodedData(
82 UTF16ToUTF8(base::i18n::ToLower(utf16)),
83 false /* do not replace space with plus */);
84 }
85
86 // Finds file browser handlers that can handle the |selected_file_url|.
87 FileBrowserHandlerList FindFileBrowserHandlersForURL(
88 Profile* profile,
89 const GURL& selected_file_url) {
90 ExtensionService* service =
91 extensions::ExtensionSystem::Get(profile)->extension_service();
92 // In unit-tests, we may not have an ExtensionService.
93 if (!service)
94 return FileBrowserHandlerList();
95
96 // We need case-insensitive matching, and pattern in the handler is already
97 // in lower case.
98 const GURL lowercase_url(EscapedUtf8ToLower(selected_file_url.spec()));
99
100 FileBrowserHandlerList results;
101 for (ExtensionSet::const_iterator iter = service->extensions()->begin();
102 iter != service->extensions()->end();
103 ++iter) {
104 const Extension* extension = iter->get();
105 if (profile->IsOffTheRecord() &&
106 !service->IsIncognitoEnabled(extension->id()))
107 continue;
108
109 FileBrowserHandler::List* handler_list =
110 FileBrowserHandler::GetHandlers(extension);
111 if (!handler_list)
112 continue;
113 for (FileBrowserHandler::List::const_iterator handler_iter =
114 handler_list->begin();
115 handler_iter != handler_list->end();
116 ++handler_iter) {
117 const FileBrowserHandler* handler = handler_iter->get();
118 if (!handler->MatchesURL(lowercase_url))
119 continue;
120
121 results.push_back(handler_iter->get());
122 }
123 }
124 return results;
125 }
126
127 // Finds a file browser handler that matches |extension_id| and |action_id|
128 // from |handler_list|. Returns a mutable iterator to the handler if
129 // found. Returns handler_list->end() if not found.
130 FileBrowserHandlerList::iterator
131 FindFileBrowserHandlerForExtensionIdAndActionId(
132 FileBrowserHandlerList* handler_list,
133 const std::string& extension_id,
134 const std::string& action_id) {
135 DCHECK(handler_list);
136
137 FileBrowserHandlerList::iterator iter = handler_list->begin();
138 while (iter != handler_list->end() &&
139 !((*iter)->extension_id() == extension_id &&
140 (*iter)->id() == action_id)) {
141 ++iter;
142 }
143 return iter;
144 }
145
146 // This class is used to execute a file browser handler task. Here's how this
147 // works:
148 //
149 // 1) Open the "external" file system
150 // 2) Set up permissions for the target files on the external file system.
151 // 3) Raise onExecute event with the action ID and entries of the target
152 // files. The event will launch the file browser handler if not active.
153 // 4) In the file browser handler, onExecute event is handled and executes the
154 // task in JavaScript.
155 //
156 // That said, the class itself does not execute a task. The task will be
157 // executed in JavaScript.
158 class FileBrowserHandlerExecutor {
159 public:
160 FileBrowserHandlerExecutor(Profile* profile,
161 const Extension* extension,
162 int32 tab_id,
163 const std::string& action_id);
164
165 // Executes the task for each file. |done| will be run with the result.
166 void Execute(const std::vector<FileSystemURL>& file_urls,
167 const file_tasks::FileTaskFinishedCallback& done);
168
169 private:
170 // This object is responsible to delete itself.
171 virtual ~FileBrowserHandlerExecutor();
172
173 struct FileDefinition {
174 FileDefinition();
175 ~FileDefinition();
176
177 base::FilePath virtual_path;
178 base::FilePath absolute_path;
179 bool is_directory;
180 };
181
182 typedef std::vector<FileDefinition> FileDefinitionList;
183
184 // Checks legitimacy of file url and grants file RO access permissions from
185 // handler (target) extension and its renderer process.
186 static FileDefinitionList SetupFileAccessPermissions(
187 scoped_refptr<fileapi::FileSystemContext> file_system_context_handler,
188 const scoped_refptr<const Extension>& handler_extension,
189 const std::vector<FileSystemURL>& file_urls);
190
191 void DidOpenFileSystem(const std::vector<FileSystemURL>& file_urls,
192 base::PlatformFileError result,
193 const std::string& file_system_name,
194 const GURL& file_system_root);
195
196 void ExecuteDoneOnUIThread(bool success);
197 void ExecuteFileActionsOnUIThread(const std::string& file_system_name,
198 const GURL& file_system_root,
199 const FileDefinitionList& file_list);
200 void SetupPermissionsAndDispatchEvent(const std::string& file_system_name,
201 const GURL& file_system_root,
202 const FileDefinitionList& file_list,
203 int handler_pid_in,
204 extensions::ExtensionHost* host);
205
206 // Registers file permissions from |handler_host_permissions_| with
207 // ChildProcessSecurityPolicy for process with id |handler_pid|.
208 void SetupHandlerHostFileAccessPermissions(
209 const FileDefinitionList& file_list,
210 const Extension* extension,
211 int handler_pid);
212
213 Profile* profile_;
214 scoped_refptr<const Extension> extension_;
215 int32 tab_id_;
216 const std::string action_id_;
217 file_tasks::FileTaskFinishedCallback done_;
218 base::WeakPtrFactory<FileBrowserHandlerExecutor> weak_ptr_factory_;
219
220 DISALLOW_COPY_AND_ASSIGN(FileBrowserHandlerExecutor);
221 };
222
223 FileBrowserHandlerExecutor::FileDefinition::FileDefinition()
224 : is_directory(false) {
225 }
226
227 FileBrowserHandlerExecutor::FileDefinition::~FileDefinition() {
228 }
229
230 // static
231 FileBrowserHandlerExecutor::FileDefinitionList
232 FileBrowserHandlerExecutor::SetupFileAccessPermissions(
233 scoped_refptr<fileapi::FileSystemContext> file_system_context_handler,
234 const scoped_refptr<const Extension>& handler_extension,
235 const std::vector<FileSystemURL>& file_urls) {
236 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
237 DCHECK(handler_extension.get());
238
239 fileapi::ExternalFileSystemBackend* backend =
240 file_system_context_handler->external_backend();
241
242 FileDefinitionList file_list;
243 for (size_t i = 0; i < file_urls.size(); ++i) {
244 const FileSystemURL& url = file_urls[i];
245
246 // Check if this file system entry exists first.
247 base::PlatformFileInfo file_info;
248
249 base::FilePath local_path = url.path();
250 base::FilePath virtual_path = url.virtual_path();
251
252 bool is_drive_file = url.type() == fileapi::kFileSystemTypeDrive;
253 DCHECK(!is_drive_file || drive::util::IsUnderDriveMountPoint(local_path));
254
255 // If the file is under drive mount point, there is no actual file to be
256 // found on the url.path().
257 if (!is_drive_file) {
258 if (!base::PathExists(local_path) ||
259 file_util::IsLink(local_path) ||
260 !file_util::GetFileInfo(local_path, &file_info)) {
261 continue;
262 }
263 }
264
265 // Grant access to this particular file to target extension. This will
266 // ensure that the target extension can access only this FS entry and
267 // prevent from traversing FS hierarchy upward.
268 backend->GrantFileAccessToExtension(
269 handler_extension->id(), virtual_path);
270
271 // Output values.
272 FileDefinition file;
273 file.virtual_path = virtual_path;
274 file.is_directory = file_info.is_directory;
275 file.absolute_path = local_path;
276 file_list.push_back(file);
277 }
278 return file_list;
279 }
280
281 FileBrowserHandlerExecutor::FileBrowserHandlerExecutor(
282 Profile* profile,
283 const Extension* extension,
284 int32 tab_id,
285 const std::string& action_id)
286 : profile_(profile),
287 extension_(extension),
288 tab_id_(tab_id),
289 action_id_(action_id),
290 weak_ptr_factory_(this) {
291 }
292
293 FileBrowserHandlerExecutor::~FileBrowserHandlerExecutor() {}
294
295 void FileBrowserHandlerExecutor::Execute(
296 const std::vector<FileSystemURL>& file_urls,
297 const file_tasks::FileTaskFinishedCallback& done) {
298 done_ = done;
299
300 // Get file system context for the extension to which onExecute event will be
301 // sent. The file access permissions will be granted to the extension in the
302 // file system context for the files in |file_urls|.
303 util::GetFileSystemContextForExtensionId(
304 profile_, extension_->id())->OpenFileSystem(
305 Extension::GetBaseURLFromExtensionId(extension_->id()).GetOrigin(),
306 fileapi::kFileSystemTypeExternal,
307 fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
308 base::Bind(&FileBrowserHandlerExecutor::DidOpenFileSystem,
309 weak_ptr_factory_.GetWeakPtr(),
310 file_urls));
311 }
312
313 void FileBrowserHandlerExecutor::DidOpenFileSystem(
314 const std::vector<FileSystemURL>& file_urls,
315 base::PlatformFileError result,
316 const std::string& file_system_name,
317 const GURL& file_system_root) {
318 if (result != base::PLATFORM_FILE_OK) {
319 ExecuteDoneOnUIThread(false);
320 return;
321 }
322
323 scoped_refptr<fileapi::FileSystemContext> file_system_context(
324 util::GetFileSystemContextForExtensionId(
325 profile_, extension_->id()));
326 BrowserThread::PostTaskAndReplyWithResult(
327 BrowserThread::FILE,
328 FROM_HERE,
329 base::Bind(&SetupFileAccessPermissions,
330 file_system_context,
331 extension_,
332 file_urls),
333 base::Bind(&FileBrowserHandlerExecutor::ExecuteFileActionsOnUIThread,
334 weak_ptr_factory_.GetWeakPtr(),
335 file_system_name,
336 file_system_root));
337 }
338
339 void FileBrowserHandlerExecutor::ExecuteDoneOnUIThread(bool success) {
340 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
341 if (!done_.is_null())
342 done_.Run(success);
343 delete this;
344 }
345
346 void FileBrowserHandlerExecutor::ExecuteFileActionsOnUIThread(
347 const std::string& file_system_name,
348 const GURL& file_system_root,
349 const FileDefinitionList& file_list) {
350 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
351
352 if (file_list.empty()) {
353 ExecuteDoneOnUIThread(false);
354 return;
355 }
356
357 int handler_pid = ExtractProcessFromExtensionId(profile_, extension_->id());
358 if (handler_pid <= 0 &&
359 !extensions::BackgroundInfo::HasLazyBackgroundPage(extension_.get())) {
360 ExecuteDoneOnUIThread(false);
361 return;
362 }
363
364 if (handler_pid > 0) {
365 SetupPermissionsAndDispatchEvent(file_system_name, file_system_root,
366 file_list, handler_pid, NULL);
367 } else {
368 // We have to wake the handler background page before we proceed.
369 extensions::LazyBackgroundTaskQueue* queue =
370 extensions::ExtensionSystem::Get(profile_)->
371 lazy_background_task_queue();
372 if (!queue->ShouldEnqueueTask(profile_, extension_.get())) {
373 ExecuteDoneOnUIThread(false);
374 return;
375 }
376 queue->AddPendingTask(
377 profile_, extension_->id(),
378 base::Bind(
379 &FileBrowserHandlerExecutor::SetupPermissionsAndDispatchEvent,
380 weak_ptr_factory_.GetWeakPtr(),
381 file_system_name,
382 file_system_root,
383 file_list,
384 handler_pid));
385 }
386 }
387
388 void FileBrowserHandlerExecutor::SetupPermissionsAndDispatchEvent(
389 const std::string& file_system_name,
390 const GURL& file_system_root,
391 const FileDefinitionList& file_list,
392 int handler_pid_in,
393 extensions::ExtensionHost* host) {
394 int handler_pid = host ? host->render_process_host()->GetID() :
395 handler_pid_in;
396
397 if (handler_pid <= 0) {
398 ExecuteDoneOnUIThread(false);
399 return;
400 }
401
402 extensions::EventRouter* event_router =
403 extensions::ExtensionSystem::Get(profile_)->event_router();
404 if (!event_router) {
405 ExecuteDoneOnUIThread(false);
406 return;
407 }
408
409 SetupHandlerHostFileAccessPermissions(
410 file_list, extension_.get(), handler_pid);
411
412 scoped_ptr<ListValue> event_args(new ListValue());
413 event_args->Append(new base::StringValue(action_id_));
414 DictionaryValue* details = new DictionaryValue();
415 event_args->Append(details);
416 // Get file definitions. These will be replaced with Entry instances by
417 // dispatchEvent() method from event_binding.js.
418 ListValue* file_entries = new ListValue();
419 details->Set("entries", file_entries);
420 for (FileDefinitionList::const_iterator iter = file_list.begin();
421 iter != file_list.end();
422 ++iter) {
423 DictionaryValue* file_def = new DictionaryValue();
424 file_entries->Append(file_def);
425 file_def->SetString("fileSystemName", file_system_name);
426 file_def->SetString("fileSystemRoot", file_system_root.spec());
427 base::FilePath root(FILE_PATH_LITERAL("/"));
428 base::FilePath full_path = root.Append(iter->virtual_path);
429 file_def->SetString("fileFullPath", full_path.value());
430 file_def->SetBoolean("fileIsDirectory", iter->is_directory);
431 }
432
433 details->SetInteger("tab_id", tab_id_);
434
435 scoped_ptr<extensions::Event> event(new extensions::Event(
436 "fileBrowserHandler.onExecute", event_args.Pass()));
437 event->restrict_to_profile = profile_;
438 event_router->DispatchEventToExtension(extension_->id(), event.Pass());
439
440 ExecuteDoneOnUIThread(true);
441 }
442
443 void FileBrowserHandlerExecutor::SetupHandlerHostFileAccessPermissions(
444 const FileDefinitionList& file_list,
445 const Extension* extension,
446 int handler_pid) {
447 const FileBrowserHandler* action = FindFileBrowserHandlerForActionId(
448 extension_, action_id_);
449 for (FileDefinitionList::const_iterator iter = file_list.begin();
450 iter != file_list.end();
451 ++iter) {
452 if (!action)
453 continue;
454 if (action->CanRead()) {
455 content::ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(
456 handler_pid, iter->absolute_path);
457 }
458 if (action->CanWrite()) {
459 content::ChildProcessSecurityPolicy::GetInstance()->
460 GrantCreateReadWriteFile(handler_pid, iter->absolute_path);
461 }
462 }
463 }
464
465 // Returns true if |extension_id| and |action_id| indicate that the file
466 // currently being handled should be opened with the browser. This function
467 // is used to handle certain action IDs of the file manager.
468 bool ShouldBeOpenedWithBrowser(const std::string& extension_id,
469 const std::string& action_id) {
470
471 return (extension_id == kFileManagerAppId &&
472 (action_id == "view-pdf" ||
473 action_id == "view-swf" ||
474 action_id == "view-in-browser" ||
475 action_id == "install-crx" ||
476 action_id == "open-hosted-generic" ||
477 action_id == "open-hosted-gdoc" ||
478 action_id == "open-hosted-gsheet" ||
479 action_id == "open-hosted-gslides"));
480 }
481
482 // Opens the files specified by |file_urls| with the browser for |profile|.
483 // Returns true on success. It's a failure if no files are opened.
484 bool OpenFilesWithBrowser(Profile* profile,
485 const std::vector<FileSystemURL>& file_urls) {
486 int num_opened = 0;
487 for (size_t i = 0; i < file_urls.size(); ++i) {
488 const FileSystemURL& file_url = file_urls[i];
489 if (chromeos::FileSystemBackend::CanHandleURL(file_url)) {
490 const base::FilePath& file_path = file_url.path();
491 num_opened += util::OpenFileWithBrowser(profile, file_path);
492 }
493 }
494 return num_opened > 0;
495 }
496
497 } // namespace
498
499 bool ExecuteFileBrowserHandler(
500 Profile* profile,
501 const Extension* extension,
502 int32 tab_id,
503 const std::string& action_id,
504 const std::vector<FileSystemURL>& file_urls,
505 const file_tasks::FileTaskFinishedCallback& done) {
506 // Forbid calling undeclared handlers.
507 if (!FindFileBrowserHandlerForActionId(extension, action_id))
508 return false;
509
510 // Some action IDs of the file manager's file browser handlers require the
511 // files to be directly opened with the browser.
512 if (ShouldBeOpenedWithBrowser(extension->id(), action_id)) {
513 return OpenFilesWithBrowser(profile, file_urls);
514 }
515
516 // The executor object will be self deleted on completion.
517 (new FileBrowserHandlerExecutor(
518 profile, extension, tab_id, action_id))->Execute(file_urls, done);
519 return true;
520 }
521
522 bool IsFallbackFileBrowserHandler(const file_tasks::TaskDescriptor& task) {
523 return (task.task_type == file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER &&
524 (task.app_id == kFileManagerAppId ||
525 task.app_id == extension_misc::kQuickOfficeComponentExtensionId ||
526 task.app_id == extension_misc::kQuickOfficeDevExtensionId ||
527 task.app_id == extension_misc::kQuickOfficeExtensionId));
528 }
529
530 FileBrowserHandlerList FindDefaultFileBrowserHandlers(
531 const PrefService& pref_service,
532 const std::vector<base::FilePath>& file_list,
533 const FileBrowserHandlerList& common_handlers) {
534 FileBrowserHandlerList default_handlers;
535
536 std::set<std::string> default_ids;
537 for (std::vector<base::FilePath>::const_iterator it = file_list.begin();
538 it != file_list.end(); ++it) {
539 std::string task_id = file_tasks::GetDefaultTaskIdFromPrefs(
540 pref_service, "", it->Extension());
541 if (!task_id.empty())
542 default_ids.insert(task_id);
543 }
544
545 const FileBrowserHandler* fallback_handler = NULL;
546 // Convert the default task IDs collected above to one of the handler pointers
547 // from common_handlers.
548 for (size_t i = 0; i < common_handlers.size(); ++i) {
549 const FileBrowserHandler* handler = common_handlers[i];
550 const file_tasks::TaskDescriptor task_descriptor(
551 handler->extension_id(),
552 file_tasks::TASK_TYPE_FILE_BROWSER_HANDLER,
553 handler->id());
554 const std::string task_id =
555 file_tasks::TaskDescriptorToId(task_descriptor);
556 std::set<std::string>::iterator default_iter = default_ids.find(task_id);
557 if (default_iter != default_ids.end()) {
558 default_handlers.push_back(handler);
559 continue;
560 }
561
562 // Remember the first fallback handler.
563 if (!fallback_handler && IsFallbackFileBrowserHandler(task_descriptor))
564 fallback_handler = handler;
565 }
566
567 // If there are no default handlers found, use fallback as default.
568 if (fallback_handler && default_handlers.empty())
569 default_handlers.push_back(fallback_handler);
570
571 return default_handlers;
572 }
573
574 FileBrowserHandlerList FindCommonFileBrowserHandlers(
575 Profile* profile,
576 const std::vector<GURL>& file_list) {
577 FileBrowserHandlerList common_handlers;
578 for (std::vector<GURL>::const_iterator it = file_list.begin();
579 it != file_list.end(); ++it) {
580 FileBrowserHandlerList handlers =
581 FindFileBrowserHandlersForURL(profile, *it);
582 // If there is nothing to do for one file, the intersection of handlers
583 // for all files will be empty at the end, so no need to check further.
584 if (handlers.empty())
585 return FileBrowserHandlerList();
586
587 // For the very first file, just copy all the elements.
588 if (it == file_list.begin()) {
589 common_handlers = handlers;
590 } else {
591 // For all additional files, find intersection between the accumulated and
592 // file specific set.
593 FileBrowserHandlerList intersection;
594 std::set_intersection(common_handlers.begin(), common_handlers.end(),
595 handlers.begin(), handlers.end(),
596 std::back_inserter(intersection));
597 common_handlers = intersection;
598 if (common_handlers.empty())
599 return FileBrowserHandlerList();
600 }
601 }
602
603 // "watch" and "gallery" are defined in the file manager's manifest.json.
604 FileBrowserHandlerList::iterator watch_iter =
605 FindFileBrowserHandlerForExtensionIdAndActionId(
606 &common_handlers, kFileManagerAppId, "watch");
607 FileBrowserHandlerList::iterator gallery_iter =
608 FindFileBrowserHandlerForExtensionIdAndActionId(
609 &common_handlers, kFileManagerAppId, "gallery");
610 if (watch_iter != common_handlers.end() &&
611 gallery_iter != common_handlers.end()) {
612 // Both "watch" and "gallery" actions are applicable which means that the
613 // selection is all videos. Showing them both is confusing, so we only keep
614 // the one that makes more sense ("watch" for single selection, "gallery"
615 // for multiple selection).
616 if (file_list.size() == 1)
617 common_handlers.erase(gallery_iter);
618 else
619 common_handlers.erase(watch_iter);
620 }
621
622 return common_handlers;
623 }
624
625 const FileBrowserHandler* FindFileBrowserHandlerForURLAndPath(
626 Profile* profile,
627 const GURL& url,
628 const base::FilePath& file_path) {
629 std::vector<GURL> file_urls;
630 file_urls.push_back(url);
631
632 FileBrowserHandlerList common_handlers =
633 FindCommonFileBrowserHandlers(profile, file_urls);
634 if (common_handlers.empty())
635 return NULL;
636
637 std::vector<base::FilePath> file_paths;
638 file_paths.push_back(file_path);
639
640 FileBrowserHandlerList default_handlers =
641 FindDefaultFileBrowserHandlers(*profile->GetPrefs(),
642 file_paths,
643 common_handlers);
644
645 // If there's none, or more than one, then we don't have a canonical default.
646 if (!default_handlers.empty()) {
647 // There should not be multiple default handlers for a single URL.
648 DCHECK_EQ(1u, default_handlers.size());
649
650 return *default_handlers.begin();
651 }
652
653 // If there are no default handlers, use first handler in the list (file
654 // manager does the same in this situation). TODO(tbarzic): This is not so
655 // optimal behaviour.
656 return *common_handlers.begin();
657 }
658
659 } // namespace file_browser_handlers
660 } // namespace file_manager
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698