This source file includes following definitions.
- GetInstance
- Add
- Remove
- Find
- FindRuntimeContext
- GetRoutingIDFromWebContents
- Create
- params_
- IsRunning
- ListenerDestroyed
- ExtensionDialogClosing
- ExtensionTerminated
- OnFileSelected
- OnMultiFilesSelected
- OnFileSelectionCanceled
- GetRenderViewHost
- NotifyListener
- AddPending
- PendingExists
- HasMultipleFileTypeChoicesImpl
- SelectFileImpl
#include "chrome/browser/ui/views/select_file_dialog_extension.h"
#include "apps/app_window.h"
#include "apps/app_window_registry.h"
#include "apps/ui/native_app_window.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/singleton.h"
#include "base/message_loop/message_loop.h"
#include "chrome/browser/app_mode/app_mode_utils.h"
#include "chrome/browser/chromeos/file_manager/app_id.h"
#include "chrome/browser/chromeos/file_manager/fileapi_util.h"
#include "chrome/browser/chromeos/file_manager/select_file_dialog_util.h"
#include "chrome/browser/chromeos/file_manager/url_util.h"
#include "chrome/browser/chromeos/login/login_web_dialog.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_view_host.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/chrome_select_file_policy.h"
#include "chrome/browser/ui/host_desktop.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/views/extensions/extension_dialog.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/extension_system.h"
#include "ui/base/base_window.h"
#include "ui/shell_dialogs/selected_file_info.h"
#include "ui/views/widget/widget.h"
using apps::AppWindow;
using content::BrowserThread;
namespace {
const int kFileManagerWidth = 972;
const int kFileManagerHeight = 640;
const int kFileManagerMinimumWidth = 320;
const int kFileManagerMinimumHeight = 240;
class PendingDialog {
public:
static PendingDialog* GetInstance();
void Add(SelectFileDialogExtension::RoutingID id,
scoped_refptr<SelectFileDialogExtension> dialog);
void Remove(SelectFileDialogExtension::RoutingID id);
scoped_refptr<SelectFileDialogExtension> Find(
SelectFileDialogExtension::RoutingID id);
private:
friend struct DefaultSingletonTraits<PendingDialog>;
typedef std::map<SelectFileDialogExtension::RoutingID,
scoped_refptr<SelectFileDialogExtension> > Map;
Map map_;
};
PendingDialog* PendingDialog::GetInstance() {
return Singleton<PendingDialog>::get();
}
void PendingDialog::Add(SelectFileDialogExtension::RoutingID id,
scoped_refptr<SelectFileDialogExtension> dialog) {
DCHECK(dialog.get());
if (map_.find(id) == map_.end())
map_.insert(std::make_pair(id, dialog));
else
DLOG(WARNING) << "Duplicate pending dialog " << id;
}
void PendingDialog::Remove(SelectFileDialogExtension::RoutingID id) {
map_.erase(id);
}
scoped_refptr<SelectFileDialogExtension> PendingDialog::Find(
SelectFileDialogExtension::RoutingID id) {
Map::const_iterator it = map_.find(id);
if (it == map_.end())
return NULL;
return it->second;
}
void FindRuntimeContext(
gfx::NativeWindow owner_window,
ui::BaseWindow** base_window,
content::WebContents** web_contents,
Profile** profile) {
*base_window = NULL;
*web_contents = NULL;
*profile = NULL;
Browser* owner_browser = NULL;
AppWindow* app_window = NULL;
if (owner_window) {
owner_browser = chrome::FindBrowserWithWindow(owner_window);
if (!owner_browser) {
app_window =
apps::AppWindowRegistry::GetAppWindowForNativeWindowAnyProfile(
owner_window);
}
}
if (app_window) {
DCHECK(!app_window->window_type_is_panel());
*base_window = app_window->GetBaseWindow();
*web_contents = app_window->web_contents();
} else {
if (!owner_browser) {
owner_browser =
chrome::FindLastActiveWithHostDesktopType(chrome::GetActiveDesktop());
}
if (owner_browser) {
*base_window = owner_browser->window();
*web_contents = owner_browser->tab_strip_model()->GetActiveWebContents();
}
}
if (chrome::IsRunningInForcedAppMode() && !(*web_contents))
*web_contents = chromeos::LoginWebDialog::GetCurrentWebContents();
CHECK(web_contents);
*profile = Profile::FromBrowserContext((*web_contents)->GetBrowserContext());
}
}
SelectFileDialogExtension::RoutingID
SelectFileDialogExtension::GetRoutingIDFromWebContents(
const content::WebContents* web_contents) {
return web_contents;
}
SelectFileDialogExtension* SelectFileDialogExtension::Create(
Listener* listener,
ui::SelectFilePolicy* policy) {
return new SelectFileDialogExtension(listener, policy);
}
SelectFileDialogExtension::SelectFileDialogExtension(
Listener* listener,
ui::SelectFilePolicy* policy)
: SelectFileDialog(listener, policy),
has_multiple_file_type_choices_(false),
routing_id_(),
profile_(NULL),
owner_window_(NULL),
selection_type_(CANCEL),
selection_index_(0),
params_(NULL) {
}
SelectFileDialogExtension::~SelectFileDialogExtension() {
if (extension_dialog_.get())
extension_dialog_->ObserverDestroyed();
}
bool SelectFileDialogExtension::IsRunning(
gfx::NativeWindow owner_window) const {
return owner_window_ == owner_window;
}
void SelectFileDialogExtension::ListenerDestroyed() {
listener_ = NULL;
params_ = NULL;
PendingDialog::GetInstance()->Remove(routing_id_);
}
void SelectFileDialogExtension::ExtensionDialogClosing(
ExtensionDialog* ) {
profile_ = NULL;
owner_window_ = NULL;
extension_dialog_ = NULL;
PendingDialog::GetInstance()->Remove(routing_id_);
NotifyListener();
}
void SelectFileDialogExtension::ExtensionTerminated(
ExtensionDialog* dialog) {
std::string extension_id = dialog->host()->extension()->id();
if (profile_) {
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&ExtensionService::ReloadExtension,
base::Unretained(extensions::ExtensionSystem::Get(profile_)
->extension_service()),
extension_id));
}
dialog->GetWidget()->Close();
}
void SelectFileDialogExtension::OnFileSelected(
RoutingID routing_id,
const ui::SelectedFileInfo& file,
int index) {
scoped_refptr<SelectFileDialogExtension> dialog =
PendingDialog::GetInstance()->Find(routing_id);
if (!dialog.get())
return;
dialog->selection_type_ = SINGLE_FILE;
dialog->selection_files_.clear();
dialog->selection_files_.push_back(file);
dialog->selection_index_ = index;
}
void SelectFileDialogExtension::OnMultiFilesSelected(
RoutingID routing_id,
const std::vector<ui::SelectedFileInfo>& files) {
scoped_refptr<SelectFileDialogExtension> dialog =
PendingDialog::GetInstance()->Find(routing_id);
if (!dialog.get())
return;
dialog->selection_type_ = MULTIPLE_FILES;
dialog->selection_files_ = files;
dialog->selection_index_ = 0;
}
void SelectFileDialogExtension::OnFileSelectionCanceled(RoutingID routing_id) {
scoped_refptr<SelectFileDialogExtension> dialog =
PendingDialog::GetInstance()->Find(routing_id);
if (!dialog.get())
return;
dialog->selection_type_ = CANCEL;
dialog->selection_files_.clear();
dialog->selection_index_ = 0;
}
content::RenderViewHost* SelectFileDialogExtension::GetRenderViewHost() {
if (extension_dialog_.get())
return extension_dialog_->host()->render_view_host();
return NULL;
}
void SelectFileDialogExtension::NotifyListener() {
if (!listener_)
return;
switch (selection_type_) {
case CANCEL:
listener_->FileSelectionCanceled(params_);
break;
case SINGLE_FILE:
listener_->FileSelectedWithExtraInfo(selection_files_[0],
selection_index_,
params_);
break;
case MULTIPLE_FILES:
listener_->MultiFilesSelectedWithExtraInfo(selection_files_, params_);
break;
default:
NOTREACHED();
break;
}
}
void SelectFileDialogExtension::AddPending(RoutingID routing_id) {
PendingDialog::GetInstance()->Add(routing_id, this);
}
bool SelectFileDialogExtension::PendingExists(RoutingID routing_id) {
return PendingDialog::GetInstance()->Find(routing_id).get() != NULL;
}
bool SelectFileDialogExtension::HasMultipleFileTypeChoicesImpl() {
return has_multiple_file_type_choices_;
}
void SelectFileDialogExtension::SelectFileImpl(
Type type,
const base::string16& title,
const base::FilePath& default_path,
const FileTypeInfo* file_types,
int file_type_index,
const base::FilePath::StringType& default_extension,
gfx::NativeWindow owner_window,
void* params) {
if (owner_window_) {
LOG(ERROR) << "File dialog already in use!";
return;
}
ui::BaseWindow* base_window = NULL;
content::WebContents* web_contents = NULL;
FindRuntimeContext(owner_window, &base_window, &web_contents, &profile_);
CHECK(profile_);
RoutingID routing_id = GetRoutingIDFromWebContents(web_contents);
if (PendingExists(routing_id))
return;
const PrefService* pref_service = profile_->GetPrefs();
DCHECK(pref_service);
base::FilePath download_default_path(
pref_service->GetFilePath(prefs::kDownloadDefaultDirectory));
base::FilePath selection_path = default_path.IsAbsolute() ?
default_path : download_default_path.Append(default_path.BaseName());
base::FilePath fallback_path = profile_->last_selected_directory().empty() ?
download_default_path : profile_->last_selected_directory();
GURL selection_url;
if (!file_manager::util::ConvertAbsoluteFilePathToFileSystemUrl(
profile_,
selection_path,
file_manager::kFileManagerAppId,
&selection_url)) {
if (!file_manager::util::ConvertAbsoluteFilePathToFileSystemUrl(
profile_,
fallback_path.Append(default_path.BaseName()),
file_manager::kFileManagerAppId,
&selection_url)) {
DVLOG(1) << "Unable to resolve the selection URL.";
}
}
GURL current_directory_url;
base::FilePath current_directory_path = selection_path.DirName();
if (!file_manager::util::ConvertAbsoluteFilePathToFileSystemUrl(
profile_,
current_directory_path,
file_manager::kFileManagerAppId,
¤t_directory_url)) {
if (!file_manager::util::ConvertAbsoluteFilePathToFileSystemUrl(
profile_,
fallback_path,
file_manager::kFileManagerAppId,
¤t_directory_url)) {
DVLOG(1) << "Unable to resolve the current directory URL for: "
<< fallback_path.value();
}
}
has_multiple_file_type_choices_ =
!file_types || (file_types->extensions.size() > 1);
GURL file_manager_url =
file_manager::util::GetFileManagerMainPageUrlWithParams(
type,
title,
current_directory_url,
selection_url,
default_path.BaseName().value(),
file_types,
file_type_index,
default_extension);
ExtensionDialog* dialog = ExtensionDialog::Show(
file_manager_url,
base_window ? base_window->GetNativeWindow() : owner_window,
profile_,
web_contents,
kFileManagerWidth,
kFileManagerHeight,
kFileManagerMinimumWidth,
kFileManagerMinimumHeight,
#if defined(USE_AURA)
file_manager::util::GetSelectFileDialogTitle(type),
#else
base::string16(),
#endif
this );
if (!dialog) {
LOG(ERROR) << "Unable to create extension dialog";
return;
}
AddPending(routing_id);
extension_dialog_ = dialog;
params_ = params;
routing_id_ = routing_id;
owner_window_ = owner_window;
}