electron/atom/browser/common_web_contents_delegate.cc
2015-06-08 13:19:56 +08:00

342 lines
11 KiB
C++

// 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 <string>
#include <vector>
#include "atom/browser/atom_javascript_dialog_manager.h"
#include "atom/browser/native_window.h"
#include "atom/browser/ui/file_dialog.h"
#include "atom/browser/web_dialog_helper.h"
#include "base/files/file_util.h"
#include "chrome/browser/ui/browser_dialogs.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 "content/public/common/renderer_preferences.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),
html_fullscreen_(false),
native_fullscreen_(false) {
}
CommonWebContentsDelegate::~CommonWebContentsDelegate() {
}
void CommonWebContentsDelegate::InitWithWebContents(
content::WebContents* web_contents,
NativeWindow* owner_window) {
owner_window_ = owner_window;
web_contents->SetDelegate(this);
// Tell renderer to handle all navigations in browser.
auto preferences = web_contents->GetMutableRendererPrefs();
preferences->browser_handles_non_local_top_level_requests = true;
preferences->browser_handles_all_top_level_requests = true;
web_contents->GetRenderViewHost()->SyncRendererPrefs();
// Create InspectableWebContents.
web_contents_.reset(brightray::InspectableWebContents::Create(web_contents));
web_contents_->SetDelegate(this);
}
void CommonWebContentsDelegate::DestroyWebContents() {
web_contents_.reset();
}
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();
}
content::WebContents* CommonWebContentsDelegate::OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) {
content::NavigationController::LoadURLParams load_url_params(params.url);
load_url_params.referrer = params.referrer;
load_url_params.transition_type = params.transition;
load_url_params.extra_headers = params.extra_headers;
load_url_params.should_replace_current_entry =
params.should_replace_current_entry;
load_url_params.is_renderer_initiated = params.is_renderer_initiated;
load_url_params.transferred_global_request_id =
params.transferred_global_request_id;
load_url_params.should_clear_history_list = true;
source->GetController().LoadURLWithParams(load_url_params);
return source;
}
void CommonWebContentsDelegate::RequestToLockMouse(
content::WebContents* web_contents,
bool user_gesture,
bool last_unlocked_by_target) {
GetWebContents()->GotResponseToLockMouseRequest(true);
}
bool CommonWebContentsDelegate::CanOverscrollContent() const {
return false;
}
bool CommonWebContentsDelegate::IsPopupOrPanel(
const content::WebContents* source) const {
return !is_guest_;
}
content::JavaScriptDialogManager*
CommonWebContentsDelegate::GetJavaScriptDialogManager(
content::WebContents* source) {
if (!dialog_manager_)
dialog_manager_.reset(new AtomJavaScriptDialogManager);
return dialog_manager_.get();
}
content::ColorChooser* CommonWebContentsDelegate::OpenColorChooser(
content::WebContents* web_contents,
SkColor color,
const std::vector<content::ColorSuggestion>& suggestions) {
return chrome::ShowColorChooser(web_contents, color);
}
void CommonWebContentsDelegate::RunFileChooser(
content::WebContents* guest,
const content::FileChooserParams& params) {
if (!web_dialog_helper_)
web_dialog_helper_.reset(new WebDialogHelper(owner_window_));
web_dialog_helper_->RunFileChooser(guest, params);
}
void CommonWebContentsDelegate::EnumerateDirectory(content::WebContents* guest,
int request_id,
const base::FilePath& path) {
if (!web_dialog_helper_)
web_dialog_helper_.reset(new WebDialogHelper(owner_window_));
web_dialog_helper_->EnumerateDirectory(guest, request_id, path);
}
void CommonWebContentsDelegate::EnterFullscreenModeForTab(
content::WebContents* source, const GURL& origin) {
if (!owner_window_)
return;
SetHtmlApiFullscreen(true);
owner_window_->NotifyWindowEnterHtmlFullScreen();
source->GetRenderViewHost()->WasResized();
}
void CommonWebContentsDelegate::ExitFullscreenModeForTab(
content::WebContents* source) {
if (!owner_window_)
return;
SetHtmlApiFullscreen(false);
owner_window_->NotifyWindowLeaveHtmlFullScreen();
source->GetRenderViewHost()->WasResized();
}
bool CommonWebContentsDelegate::IsFullscreenForTabOrPending(
const content::WebContents* source) const {
return html_fullscreen_;
}
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<base::FilePath> 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,
&registered_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<base::StringValue> error_string_value(
new base::StringValue(std::string()));
scoped_ptr<base::DictionaryValue> 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);
}
void CommonWebContentsDelegate::SetHtmlApiFullscreen(bool enter_fullscreen) {
// Window is already in fullscreen mode, save the state.
if (enter_fullscreen && owner_window_->IsFullscreen()) {
native_fullscreen_ = true;
html_fullscreen_ = true;
return;
}
// Exit html fullscreen state but not window's fullscreen mode.
if (!enter_fullscreen && native_fullscreen_) {
html_fullscreen_ = false;
return;
}
owner_window_->SetFullScreen(enter_fullscreen);
html_fullscreen_ = enter_fullscreen;
native_fullscreen_ = false;
}
} // namespace atom