15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CHROME_BROWSER_FILE_SELECT_HELPER_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_BROWSER_FILE_SELECT_HELPER_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/gtest_prod_util.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_observer.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_registrar.h" 157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "content/public/common/file_chooser_params.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/directory_lister.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/shell_dialogs/select_file_dialog.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Profile; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RenderViewHost; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WebContents; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct SelectedFileInfo; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class handles file-selection requests coming from WebUI elements 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (via the extensions::ExtensionHost class). It implements both the 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// initialisation and listener functions for file-selection dialogs. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FileSelectHelper 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public base::RefCountedThreadSafe<FileSelectHelper>, 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public ui::SelectFileDialog::Listener, 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public content::NotificationObserver { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Show the file chooser dialog. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void RunFileChooser(content::WebContents* tab, 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::FileChooserParams& params); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Enumerates all the files in directory. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void EnumerateDirectory(content::WebContents* tab, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int request_id, 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& path); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCountedThreadSafe<FileSelectHelper>; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(FileSelectHelperTest, IsAcceptTypeValid); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit FileSelectHelper(Profile* profile); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~FileSelectHelper(); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Utility class which can listen for directory lister events and relay 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // them to the main object with the correct tracking id. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class DirectoryListerDispatchDelegate 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public net::DirectoryLister::DirectoryListerDelegate { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DirectoryListerDispatchDelegate(FileSelectHelper* parent, int id) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : parent_(parent), 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id_(id) {} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~DirectoryListerDispatchDelegate() {} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnListFile( 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::DirectoryLister::DirectoryListerData& data) OVERRIDE; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnListDone(int error) OVERRIDE; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This FileSelectHelper owns this object. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FileSelectHelper* parent_; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int id_; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(DirectoryListerDispatchDelegate); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RunFileChooser(content::RenderViewHost* render_view_host, 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::WebContents* web_contents, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::FileChooserParams& params); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RunFileChooserOnFileThread( 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::FileChooserParams& params); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RunFileChooserOnUIThread( 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::FileChooserParams& params); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cleans up and releases this instance. This must be called after the last 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // callback is received from the file chooser dialog. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RunFileChooserEnd(); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SelectFileDialog::Listener overrides. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void FileSelected( 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& path, int index, void* params) OVERRIDE; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void FileSelectedWithExtraInfo( 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::SelectedFileInfo& file, 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index, 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* params) OVERRIDE; 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void MultiFilesSelected(const std::vector<base::FilePath>& files, 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* params) OVERRIDE; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void MultiFilesSelectedWithExtraInfo( 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<ui::SelectedFileInfo>& files, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* params) OVERRIDE; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void FileSelectionCanceled(void* params) OVERRIDE; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // content::NotificationObserver overrides. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Observe(int type, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) OVERRIDE; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void EnumerateDirectory(int request_id, 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderViewHost* render_view_host, 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& path); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Kicks off a new directory enumeration. 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void StartNewEnumeration(const base::FilePath& path, 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int request_id, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderViewHost* render_view_host); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Callbacks from directory enumeration. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnListFile( 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int id, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::DirectoryLister::DirectoryListerData& data); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnListDone(int id, int error); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cleans up and releases this instance. This must be called after the last 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // callback is received from the enumeration code. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void EnumerateDirectoryEnd(); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Helper method to get allowed extensions for select file dialog from 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the specified accept types as defined in the spec: 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://whatwg.org/html/number-state.html#attr-input-accept 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |accept_types| contains only valid lowercased MIME types or file extensions 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // beginning with a period (.). 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static scoped_ptr<ui::SelectFileDialog::FileTypeInfo> 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetFileTypesFromAcceptType( 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::vector<base::string16>& accept_types); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check the accept type is valid. It is expected to be all lower case with 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // no whitespace. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool IsAcceptTypeValid(const std::string& accept_type); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Profile used to set/retrieve the last used directory. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile_; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The RenderViewHost and WebContents for the page showing a file dialog 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (may only be one such dialog). 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderViewHost* render_view_host_; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::WebContents* web_contents_; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Dialog box used for choosing files to upload from file form fields. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<ui::SelectFileDialog> select_file_dialog_; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ui::SelectFileDialog::FileTypeInfo> select_file_types_; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The type of file dialog last shown. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::SelectFileDialog::Type dialog_type_; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // The mode of file dialog last shown. 1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch content::FileChooserParams::Mode dialog_mode_; 1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Maintain a list of active directory enumerations. These could come from 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the file select dialog or from drag-and-drop of directories, so there could 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be more than one going on at a time. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct ActiveDirectoryEnumeration; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<int, ActiveDirectoryEnumeration*> directory_enumerations_; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Registrar for notifications regarding our RenderViewHost. 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationRegistrar notification_registrar_; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(FileSelectHelper); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CHROME_BROWSER_FILE_SELECT_HELPER_H_ 168