// Copyright (c) 2015 GitHub, Inc. // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. #include "atom/browser/common_web_contents_delegate.h" #include "atom/browser/atom_javascript_dialog_manager.h" #include "atom/browser/native_window.h" #include "atom/browser/ui/file_dialog.h" #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "storage/browser/fileapi/isolated_context.h" namespace atom { namespace { struct FileSystem { FileSystem() { } FileSystem(const std::string& file_system_name, const std::string& root_url, const std::string& file_system_path) : file_system_name(file_system_name), root_url(root_url), file_system_path(file_system_path) { } std::string file_system_name; std::string root_url; std::string file_system_path; }; std::string RegisterFileSystem(content::WebContents* web_contents, const base::FilePath& path, std::string* registered_name) { auto isolated_context = storage::IsolatedContext::GetInstance(); std::string file_system_id = isolated_context->RegisterFileSystemForPath( storage::kFileSystemTypeNativeLocal, std::string(), path, registered_name); content::ChildProcessSecurityPolicy* policy = content::ChildProcessSecurityPolicy::GetInstance(); content::RenderViewHost* render_view_host = web_contents->GetRenderViewHost(); int renderer_id = render_view_host->GetProcess()->GetID(); policy->GrantReadFileSystem(renderer_id, file_system_id); policy->GrantWriteFileSystem(renderer_id, file_system_id); policy->GrantCreateFileForFileSystem(renderer_id, file_system_id); policy->GrantDeleteFromFileSystem(renderer_id, file_system_id); if (!policy->CanReadFile(renderer_id, path)) policy->GrantReadFile(renderer_id, path); return file_system_id; } FileSystem CreateFileSystemStruct( content::WebContents* web_contents, const std::string& file_system_id, const std::string& registered_name, const std::string& file_system_path) { const GURL origin = web_contents->GetURL().GetOrigin(); std::string file_system_name = storage::GetIsolatedFileSystemName(origin, file_system_id); std::string root_url = storage::GetIsolatedFileSystemRootURIString( origin, file_system_id, registered_name); return FileSystem(file_system_name, root_url, file_system_path); } base::DictionaryValue* CreateFileSystemValue(const FileSystem& file_system) { base::DictionaryValue* file_system_value = new base::DictionaryValue(); file_system_value->SetString("fileSystemName", file_system.file_system_name); file_system_value->SetString("rootURL", file_system.root_url); file_system_value->SetString("fileSystemPath", file_system.file_system_path); return file_system_value; } } // namespace CommonWebContentsDelegate::CommonWebContentsDelegate(bool is_guest) : is_guest_(is_guest), owner_window_(nullptr) { } CommonWebContentsDelegate::~CommonWebContentsDelegate() { } void CommonWebContentsDelegate::InitWithWebContents( content::WebContents* web_contents, NativeWindow* owner_window) { owner_window_ = owner_window; web_contents->SetDelegate(this); // Create InspectableWebContents. web_contents_.reset(brightray::InspectableWebContents::Create(web_contents)); web_contents_->SetDelegate(this); } void CommonWebContentsDelegate::DestroyWebContents() { web_contents_.reset(); } content::JavaScriptDialogManager* CommonWebContentsDelegate::GetJavaScriptDialogManager( content::WebContents* source) { if (!dialog_manager_) dialog_manager_.reset(new AtomJavaScriptDialogManager); return dialog_manager_.get(); } content::WebContents* CommonWebContentsDelegate::GetWebContents() const { if (!web_contents_) return nullptr; return web_contents_->GetWebContents(); } content::WebContents* CommonWebContentsDelegate::GetDevToolsWebContents() const { if (!web_contents_) return nullptr; return web_contents_->GetDevToolsWebContents(); } void CommonWebContentsDelegate::DevToolsSaveToFile( const std::string& url, const std::string& content, bool save_as) { base::FilePath path; PathsMap::iterator it = saved_files_.find(url); if (it != saved_files_.end() && !save_as) { path = it->second; } else { file_dialog::Filters filters; base::FilePath default_path(base::FilePath::FromUTF8Unsafe(url)); if (!file_dialog::ShowSaveDialog(owner_window_, url, default_path, filters, &path)) { base::StringValue url_value(url); web_contents_->CallClientFunction( "DevToolsAPI.canceledSaveURL", &url_value, nullptr, nullptr); return; } } saved_files_[url] = path; base::WriteFile(path, content.data(), content.size()); // Notify devtools. base::StringValue url_value(url); web_contents_->CallClientFunction( "DevToolsAPI.savedURL", &url_value, nullptr, nullptr); } void CommonWebContentsDelegate::DevToolsAppendToFile( const std::string& url, const std::string& content) { PathsMap::iterator it = saved_files_.find(url); if (it == saved_files_.end()) return; base::AppendToFile(it->second, content.data(), content.size()); // Notify devtools. base::StringValue url_value(url); web_contents_->CallClientFunction( "DevToolsAPI.appendedToURL", &url_value, nullptr, nullptr); } void CommonWebContentsDelegate::DevToolsAddFileSystem() { file_dialog::Filters filters; base::FilePath default_path; std::vector paths; int flag = file_dialog::FILE_DIALOG_OPEN_DIRECTORY; if (!file_dialog::ShowOpenDialog(owner_window_, "", default_path, filters, flag, &paths)) return; base::FilePath path = paths[0]; std::string registered_name; std::string file_system_id = RegisterFileSystem(GetDevToolsWebContents(), path, ®istered_name); WorkspaceMap::iterator it = saved_paths_.find(file_system_id); if (it != saved_paths_.end()) return; saved_paths_[file_system_id] = path; FileSystem file_system = CreateFileSystemStruct(GetDevToolsWebContents(), file_system_id, registered_name, path.AsUTF8Unsafe()); scoped_ptr error_string_value( new base::StringValue(std::string())); scoped_ptr file_system_value; if (!file_system.file_system_path.empty()) file_system_value.reset(CreateFileSystemValue(file_system)); web_contents_->CallClientFunction( "DevToolsAPI.fileSystemAdded", error_string_value.get(), file_system_value.get(), nullptr); } void CommonWebContentsDelegate::DevToolsRemoveFileSystem( const std::string& file_system_path) { if (!web_contents_) return; base::FilePath path = base::FilePath::FromUTF8Unsafe(file_system_path); storage::IsolatedContext::GetInstance()->RevokeFileSystemByPath(path); for (auto it = saved_paths_.begin(); it != saved_paths_.end(); ++it) if (it->second == path) { saved_paths_.erase(it); break; } base::StringValue file_system_path_value(file_system_path); web_contents_->CallClientFunction( "DevToolsAPI.fileSystemRemoved", &file_system_path_value, nullptr, nullptr); } } // namespace atom