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