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)#include "chrome/browser/ui/views/select_file_dialog_extension.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "apps/native_app_window.h" 8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "apps/shell_window.h" 94311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#include "apps/shell_window_registry.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h" 159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_host.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_system.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_tab_helper.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_finder.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_list.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/chrome_select_file_policy.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/host_desktop.h" 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/extensions/extension_dialog.h" 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/pref_names.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/base/base_window.h" 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/shell_dialogs/selected_file_info.h" 35a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ui/views/widget/widget.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing apps::ShellWindow; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kFileManagerWidth = 972; // pixels 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kFileManagerHeight = 640; // pixels 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Holds references to file manager dialogs that have callbacks pending 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to their listeners. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PendingDialog { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static PendingDialog* GetInstance(); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Add(int32 tab_id, scoped_refptr<SelectFileDialogExtension> dialog); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Remove(int32 tab_id); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<SelectFileDialogExtension> Find(int32 tab_id); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend struct DefaultSingletonTraits<PendingDialog>; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::map<int32, scoped_refptr<SelectFileDialogExtension> > Map; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Map map_; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PendingDialog* PendingDialog::GetInstance() { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Singleton<PendingDialog>::get(); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PendingDialog::Add(int32 tab_id, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<SelectFileDialogExtension> dialog) { 677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DCHECK(dialog.get()); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (map_.find(tab_id) == map_.end()) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) map_.insert(std::make_pair(tab_id, dialog)); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "Duplicate pending dialog " << tab_id; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PendingDialog::Remove(int32 tab_id) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) map_.erase(tab_id); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<SelectFileDialogExtension> PendingDialog::Find(int32 tab_id) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Map::const_iterator it = map_.find(tab_id); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it == map_.end()) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return it->second; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////// 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(jamescook): Move this into a new file shell_dialogs_chromeos.cc 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SelectFileDialogExtension* SelectFileDialogExtension::Create( 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Listener* listener, 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::SelectFilePolicy* policy) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new SelectFileDialogExtension(listener, policy); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SelectFileDialogExtension::SelectFileDialogExtension( 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Listener* listener, 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::SelectFilePolicy* policy) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : SelectFileDialog(listener, policy), 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_multiple_file_type_choices_(false), 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_id_(0), 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_(NULL), 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) owner_window_(NULL), 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_type_(CANCEL), 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_index_(0), 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params_(NULL) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SelectFileDialogExtension::~SelectFileDialogExtension() { 1117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (extension_dialog_.get()) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_dialog_->ObserverDestroyed(); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SelectFileDialogExtension::IsRunning( 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::NativeWindow owner_window) const { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return owner_window_ == owner_window; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogExtension::ListenerDestroyed() { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listener_ = NULL; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params_ = NULL; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PendingDialog::GetInstance()->Remove(tab_id_); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogExtension::ExtensionDialogClosing( 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionDialog* /*dialog*/) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_ = NULL; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) owner_window_ = NULL; 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Release our reference to the underlying dialog to allow it to close. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_dialog_ = NULL; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PendingDialog::GetInstance()->Remove(tab_id_); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Actually invoke the appropriate callback on our listener. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyListener(); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogExtension::ExtensionTerminated( 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionDialog* dialog) { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The extension would have been unloaded because of the termination, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reload it. 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string extension_id = dialog->host()->extension()->id(); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reload the extension after a bit; the extension may not have been unloaded 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // yet. We don't want to try to reload the extension only to have the Unload 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // code execute after us and re-unload the extension. 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(rkc): This is ugly. The ideal solution is that we shouldn't need to 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reload the extension at all - when we try to open the extension the next 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time, the extension subsystem would automatically reload it for us. At 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this time though this is broken because of some faulty wiring in 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ExtensionProcessManager::CreateViewHost. Once that is fixed, remove this. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_) { 152b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::MessageLoop::current()->PostTask( 153b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) FROM_HERE, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&ExtensionService::ReloadExtension, 155b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::Unretained(extensions::ExtensionSystem::Get(profile_) 156b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ->extension_service()), 157b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) extension_id)); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 160a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) dialog->GetWidget()->Close(); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogExtension::OnFileSelected( 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 tab_id, 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::SelectedFileInfo& file, 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index) { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<SelectFileDialogExtension> dialog = 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PendingDialog::GetInstance()->Find(tab_id); 1707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!dialog.get()) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dialog->selection_type_ = SINGLE_FILE; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dialog->selection_files_.clear(); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dialog->selection_files_.push_back(file); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dialog->selection_index_ = index; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogExtension::OnMultiFilesSelected( 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 tab_id, 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<ui::SelectedFileInfo>& files) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<SelectFileDialogExtension> dialog = 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PendingDialog::GetInstance()->Find(tab_id); 1847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!dialog.get()) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dialog->selection_type_ = MULTIPLE_FILES; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dialog->selection_files_ = files; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dialog->selection_index_ = 0; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogExtension::OnFileSelectionCanceled(int32 tab_id) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<SelectFileDialogExtension> dialog = 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PendingDialog::GetInstance()->Find(tab_id); 1957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!dialog.get()) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dialog->selection_type_ = CANCEL; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dialog->selection_files_.clear(); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dialog->selection_index_ = 0; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)content::RenderViewHost* SelectFileDialogExtension::GetRenderViewHost() { 2037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (extension_dialog_.get()) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return extension_dialog_->host()->render_view_host(); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogExtension::NotifyListener() { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!listener_) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (selection_type_) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CANCEL: 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listener_->FileSelectionCanceled(params_); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SINGLE_FILE: 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listener_->FileSelectedWithExtraInfo(selection_files_[0], 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_index_, 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params_); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case MULTIPLE_FILES: 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listener_->MultiFilesSelectedWithExtraInfo(selection_files_, params_); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogExtension::AddPending(int32 tab_id) { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PendingDialog::GetInstance()->Add(tab_id, this); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SelectFileDialogExtension::PendingExists(int32 tab_id) { 2357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return PendingDialog::GetInstance()->Find(tab_id).get() != NULL; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SelectFileDialogExtension::HasMultipleFileTypeChoicesImpl() { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return has_multiple_file_type_choices_; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogExtension::SelectFileImpl( 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Type type, 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& title, 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& default_path, 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FileTypeInfo* file_types, 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int file_type_index, 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath::StringType& default_extension, 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::NativeWindow owner_window, 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* params) { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (owner_window_) { 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "File dialog already in use!"; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The base window to associate the dialog with. 25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ui::BaseWindow* base_window = NULL; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The web contents to associate the dialog with. 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::WebContents* web_contents = NULL; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // To get the base_window and profile, either a Browser or ShellWindow is 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // needed. 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Browser* owner_browser = NULL; 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ShellWindow* shell_window = NULL; 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If owner_window is supplied, use that to find a browser or a shell window. 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (owner_window) { 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) owner_browser = chrome::FindBrowserWithWindow(owner_window); 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!owner_browser) { 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If an owner_window was supplied but we couldn't find a browser, this 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // could be for a shell window. 2734311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch shell_window = apps::ShellWindowRegistry:: 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetShellWindowForNativeWindowAnyProfile(owner_window); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (shell_window) { 279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (shell_window->window_type_is_panel()) { 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NOTREACHED() << "File dialog opened by panel."; 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base_window = shell_window->GetBaseWindow(); 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) web_contents = shell_window->web_contents(); 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the owning window is still unknown, this could be a background page or 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and extension popup. Use the last active browser. 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!owner_browser) { 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) owner_browser = 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome::FindLastActiveWithHostDesktopType(chrome::GetActiveDesktop()); 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(owner_browser); 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!owner_browser) { 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Could not find browser or shell window for popup."; 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base_window = owner_browser->window(); 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) web_contents = owner_browser->tab_strip_model()->GetActiveWebContents(); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(base_window); 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(web_contents); 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext()); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(profile_); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if we have another dialog opened for the contents. It's unlikely, but 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // possible. If there is no web contents use a tab_id of -1. A dialog without 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // an associated web contents will be shown full-screen; only one at a time 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is allowed in this state. 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 tab_id = SessionID::IdForTab(web_contents); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (PendingExists(tab_id)) { 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "Pending dialog exists with id " << tab_id; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath default_dialog_path; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PrefService* pref_service = profile_->GetPrefs(); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (default_path.empty() && pref_service) { 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default_dialog_path = 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pref_service->GetFilePath(prefs::kDownloadDefaultDirectory); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default_dialog_path = default_path; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath virtual_path; 3287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::FilePath fallback_path = profile_->last_selected_directory().Append( 3297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) default_dialog_path.BaseName()); 330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If an absolute path is specified as the default path, convert it to the 331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // virtual path in the file browser extension. Due to the current design, 332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // an invalid temporal cache file path may passed as |default_dialog_path| 333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // (crbug.com/178013 #9-#11). In such a case, we use the last selected 334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // directory as a workaround. Real fix is tracked at crbug.com/110119. 335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (default_dialog_path.IsAbsolute() && 336a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) (file_manager::util::ConvertFileToRelativeFileSystemPath( 337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) profile_, kFileBrowserDomain, default_dialog_path, &virtual_path) || 338a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) file_manager::util::ConvertFileToRelativeFileSystemPath( 3397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) profile_, kFileBrowserDomain, fallback_path, &virtual_path))) { 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual_path = base::FilePath("/").Append(virtual_path); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If the path was relative, or failed to convert, just use the base name, 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual_path = default_dialog_path.BaseName(); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_multiple_file_type_choices_ = 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_types ? file_types->extensions.size() > 1 : true; 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 349a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) GURL file_browser_url = file_manager::util::GetFileBrowserUrlWithParams( 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type, title, virtual_path, file_types, file_type_index, 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default_extension); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionDialog* dialog = ExtensionDialog::Show(file_browser_url, 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base_window, profile_, web_contents, 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kFileManagerWidth, kFileManagerHeight, 356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kFileManagerWidth, 357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kFileManagerHeight, 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA) 359a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) file_manager::util::GetTitleFromType(type), 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // HTML-based header used. 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16(), 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this /* ExtensionDialog::Observer */); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dialog) { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Unable to create extension dialog"; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Connect our listener to FileDialogFunction's per-tab callbacks. 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddPending(tab_id); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_dialog_ = dialog; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params_ = params; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_id_ = tab_id; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) owner_window_ = owner_window; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 378