Merge pull request #1097 from atom/fix-webview-race-condition
Fix the race condition when updating webview info
This commit is contained in:
commit
0b694dffd8
12 changed files with 248 additions and 303 deletions
7
atom.gyp
7
atom.gyp
|
@ -88,6 +88,7 @@
|
||||||
'atom/browser/api/atom_api_tray.h',
|
'atom/browser/api/atom_api_tray.h',
|
||||||
'atom/browser/api/atom_api_web_contents.cc',
|
'atom/browser/api/atom_api_web_contents.cc',
|
||||||
'atom/browser/api/atom_api_web_contents.h',
|
'atom/browser/api/atom_api_web_contents.h',
|
||||||
|
'atom/browser/api/atom_api_web_view_manager.cc',
|
||||||
'atom/browser/api/atom_api_window.cc',
|
'atom/browser/api/atom_api_window.cc',
|
||||||
'atom/browser/api/atom_api_window.h',
|
'atom/browser/api/atom_api_window.h',
|
||||||
'atom/browser/api/event.cc',
|
'atom/browser/api/event.cc',
|
||||||
|
@ -190,10 +191,8 @@
|
||||||
'atom/browser/ui/x/window_state_watcher.h',
|
'atom/browser/ui/x/window_state_watcher.h',
|
||||||
'atom/browser/ui/x/x_window_utils.cc',
|
'atom/browser/ui/x/x_window_utils.cc',
|
||||||
'atom/browser/ui/x/x_window_utils.h',
|
'atom/browser/ui/x/x_window_utils.h',
|
||||||
'atom/browser/web_view/web_view_manager.cc',
|
'atom/browser/web_view_manager.cc',
|
||||||
'atom/browser/web_view/web_view_manager.h',
|
'atom/browser/web_view_manager.h',
|
||||||
'atom/browser/web_view/web_view_renderer_state.cc',
|
|
||||||
'atom/browser/web_view/web_view_renderer_state.h',
|
|
||||||
'atom/browser/web_dialog_helper.cc',
|
'atom/browser/web_dialog_helper.cc',
|
||||||
'atom/browser/web_dialog_helper.h',
|
'atom/browser/web_dialog_helper.h',
|
||||||
'atom/browser/window_list.cc',
|
'atom/browser/window_list.cc',
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "atom/browser/atom_browser_context.h"
|
#include "atom/browser/atom_browser_context.h"
|
||||||
#include "atom/browser/native_window.h"
|
#include "atom/browser/native_window.h"
|
||||||
#include "atom/browser/web_dialog_helper.h"
|
#include "atom/browser/web_dialog_helper.h"
|
||||||
#include "atom/browser/web_view/web_view_renderer_state.h"
|
#include "atom/browser/web_view_manager.h"
|
||||||
#include "atom/common/api/api_messages.h"
|
#include "atom/common/api/api_messages.h"
|
||||||
#include "atom/common/native_mate_converters/gfx_converter.h"
|
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||||
|
@ -39,9 +39,9 @@ v8::Persistent<v8::ObjectTemplate> template_;
|
||||||
|
|
||||||
// Get the window that has the |guest| embedded.
|
// Get the window that has the |guest| embedded.
|
||||||
NativeWindow* GetWindowFromGuest(const content::WebContents* guest) {
|
NativeWindow* GetWindowFromGuest(const content::WebContents* guest) {
|
||||||
int guest_process_id = guest->GetRenderProcessHost()->GetID();
|
auto process = guest->GetRenderProcessHost();
|
||||||
WebViewRendererState::WebViewInfo info;
|
WebViewManager::WebViewInfo info;
|
||||||
if (!WebViewRendererState::GetInstance()->GetInfo(guest_process_id, &info))
|
if (WebViewManager::GetInfoForProcess(process, &info))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return NativeWindow::FromRenderView(
|
return NativeWindow::FromRenderView(
|
||||||
info.embedder->GetRenderProcessHost()->GetID(),
|
info.embedder->GetRenderProcessHost()->GetID(),
|
||||||
|
|
92
atom/browser/api/atom_api_web_view_manager.cc
Normal file
92
atom/browser/api/atom_api_web_view_manager.cc
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
// 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/api/atom_api_web_contents.h"
|
||||||
|
#include "atom/browser/atom_browser_context.h"
|
||||||
|
#include "atom/browser/web_view_manager.h"
|
||||||
|
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||||
|
#include "native_mate/dictionary.h"
|
||||||
|
#include "net/base/filename_util.h"
|
||||||
|
|
||||||
|
#include "atom/common/node_includes.h"
|
||||||
|
|
||||||
|
namespace mate {
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Converter<content::WebContents*> {
|
||||||
|
static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
|
||||||
|
content::WebContents** out) {
|
||||||
|
atom::api::WebContents* contents;
|
||||||
|
if (!Converter<atom::api::WebContents*>::FromV8(isolate, val, &contents))
|
||||||
|
return false;
|
||||||
|
*out = contents->web_contents();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Converter<atom::WebViewManager::WebViewInfo> {
|
||||||
|
static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
|
||||||
|
atom::WebViewManager::WebViewInfo* out) {
|
||||||
|
Dictionary options;
|
||||||
|
if (!ConvertFromV8(isolate, val, &options))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
GURL preload_url;
|
||||||
|
if (!options.Get("preloadUrl", &preload_url))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!preload_url.is_empty() &&
|
||||||
|
!net::FileURLToFilePath(preload_url, &(out->preload_script)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return options.Get("nodeIntegration", &(out->node_integration)) &&
|
||||||
|
options.Get("plugins", &(out->plugins)) &&
|
||||||
|
options.Get("disableWebSecurity", &(out->disable_web_security));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mate
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
atom::WebViewManager* GetWebViewManager(content::WebContents* web_contents) {
|
||||||
|
auto context = web_contents->GetBrowserContext();
|
||||||
|
if (context) {
|
||||||
|
auto manager = context->GetGuestManager();
|
||||||
|
return static_cast<atom::WebViewManager*>(manager);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddGuest(int guest_instance_id,
|
||||||
|
int element_instance_id,
|
||||||
|
content::WebContents* embedder,
|
||||||
|
content::WebContents* guest_web_contents,
|
||||||
|
atom::WebViewManager::WebViewInfo info) {
|
||||||
|
auto manager = GetWebViewManager(embedder);
|
||||||
|
if (manager) {
|
||||||
|
info.guest_instance_id = guest_instance_id;
|
||||||
|
info.embedder = embedder;
|
||||||
|
manager->AddGuest(guest_instance_id, element_instance_id, embedder,
|
||||||
|
guest_web_contents, info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveGuest(content::WebContents* embedder, int guest_instance_id) {
|
||||||
|
auto manager = GetWebViewManager(embedder);
|
||||||
|
if (manager)
|
||||||
|
manager->RemoveGuest(guest_instance_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Initialize(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> unused,
|
||||||
|
v8::Handle<v8::Context> context, void* priv) {
|
||||||
|
mate::Dictionary dict(context->GetIsolate(), exports);
|
||||||
|
dict.SetMethod("addGuest", &AddGuest);
|
||||||
|
dict.SetMethod("removeGuest", &RemoveGuest);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_web_view_manager, Initialize)
|
|
@ -9,7 +9,7 @@
|
||||||
#include "atom/browser/atom_browser_main_parts.h"
|
#include "atom/browser/atom_browser_main_parts.h"
|
||||||
#include "atom/browser/atom_speech_recognition_manager_delegate.h"
|
#include "atom/browser/atom_speech_recognition_manager_delegate.h"
|
||||||
#include "atom/browser/native_window.h"
|
#include "atom/browser/native_window.h"
|
||||||
#include "atom/browser/web_view/web_view_renderer_state.h"
|
#include "atom/browser/web_view_manager.h"
|
||||||
#include "atom/browser/window_list.h"
|
#include "atom/browser/window_list.h"
|
||||||
#include "atom/common/options_switches.h"
|
#include "atom/common/options_switches.h"
|
||||||
#include "base/command_line.h"
|
#include "base/command_line.h"
|
||||||
|
@ -97,16 +97,15 @@ void AtomBrowserClient::OverrideWebkitPrefs(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom preferences of guest page.
|
// Custom preferences of guest page.
|
||||||
int guest_process_id = render_view_host->GetProcess()->GetID();
|
auto process = render_view_host->GetProcess();
|
||||||
WebViewRendererState::WebViewInfo info;
|
WebViewManager::WebViewInfo info;
|
||||||
if (WebViewRendererState::GetInstance()->GetInfo(guest_process_id, &info)) {
|
if (WebViewManager::GetInfoForProcess(process, &info)) {
|
||||||
prefs->web_security_enabled = !info.disable_web_security;
|
prefs->web_security_enabled = !info.disable_web_security;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeWindow* window = NativeWindow::FromRenderView(
|
NativeWindow* window = NativeWindow::FromRenderView(
|
||||||
render_view_host->GetProcess()->GetID(),
|
process->GetID(), render_view_host->GetRoutingID());
|
||||||
render_view_host->GetRoutingID());
|
|
||||||
if (window)
|
if (window)
|
||||||
window->OverrideWebkitPrefs(url, prefs);
|
window->OverrideWebkitPrefs(url, prefs);
|
||||||
}
|
}
|
||||||
|
@ -154,8 +153,9 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches(
|
||||||
window->AppendExtraCommandLineSwitches(command_line, child_process_id);
|
window->AppendExtraCommandLineSwitches(command_line, child_process_id);
|
||||||
} else {
|
} else {
|
||||||
// Append commnad line arguments for guest web view.
|
// Append commnad line arguments for guest web view.
|
||||||
WebViewRendererState::WebViewInfo info;
|
auto child_process = content::RenderProcessHost::FromID(child_process_id);
|
||||||
if (WebViewRendererState::GetInstance()->GetInfo(child_process_id, &info)) {
|
WebViewManager::WebViewInfo info;
|
||||||
|
if (WebViewManager::GetInfoForProcess(child_process, &info)) {
|
||||||
command_line->AppendSwitchASCII(
|
command_line->AppendSwitchASCII(
|
||||||
switches::kGuestInstanceID,
|
switches::kGuestInstanceID,
|
||||||
base::IntToString(info.guest_instance_id));
|
base::IntToString(info.guest_instance_id));
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "atom/browser/atom_browser_main_parts.h"
|
#include "atom/browser/atom_browser_main_parts.h"
|
||||||
#include "atom/browser/net/atom_url_request_job_factory.h"
|
#include "atom/browser/net/atom_url_request_job_factory.h"
|
||||||
#include "atom/browser/net/asar/asar_protocol_handler.h"
|
#include "atom/browser/net/asar/asar_protocol_handler.h"
|
||||||
#include "atom/browser/web_view/web_view_manager.h"
|
#include "atom/browser/web_view_manager.h"
|
||||||
#include "atom/common/options_switches.h"
|
#include "atom/common/options_switches.h"
|
||||||
#include "base/command_line.h"
|
#include "base/command_line.h"
|
||||||
#include "base/threading/sequenced_worker_pool.h"
|
#include "base/threading/sequenced_worker_pool.h"
|
||||||
|
|
|
@ -39,7 +39,7 @@ createGuest = (embedder, params) ->
|
||||||
# Destroy guest when the embedder is gone or navigated.
|
# Destroy guest when the embedder is gone or navigated.
|
||||||
destroyEvents = ['destroyed', 'crashed', 'did-navigate-to-different-page']
|
destroyEvents = ['destroyed', 'crashed', 'did-navigate-to-different-page']
|
||||||
destroy = ->
|
destroy = ->
|
||||||
destroyGuest id if guestInstances[id]?
|
destroyGuest embedder, id if guestInstances[id]?
|
||||||
embedder.once event, destroy for event in destroyEvents
|
embedder.once event, destroy for event in destroyEvents
|
||||||
guest.once 'destroyed', ->
|
guest.once 'destroyed', ->
|
||||||
embedder.removeListener event, destroy for event in destroyEvents
|
embedder.removeListener event, destroy for event in destroyEvents
|
||||||
|
@ -90,7 +90,7 @@ attachGuest = (embedder, elementInstanceId, guestInstanceId, params) ->
|
||||||
return unless oldGuestInstanceId != guestInstanceId
|
return unless oldGuestInstanceId != guestInstanceId
|
||||||
|
|
||||||
return unless guestInstances[oldGuestInstanceId]?
|
return unless guestInstances[oldGuestInstanceId]?
|
||||||
destroyGuest oldGuestInstanceId
|
destroyGuest embedder, oldGuestInstanceId
|
||||||
|
|
||||||
webViewManager.addGuest guestInstanceId, elementInstanceId, embedder, guest,
|
webViewManager.addGuest guestInstanceId, elementInstanceId, embedder, guest,
|
||||||
nodeIntegration: params.nodeintegration
|
nodeIntegration: params.nodeintegration
|
||||||
|
@ -103,8 +103,8 @@ attachGuest = (embedder, elementInstanceId, guestInstanceId, params) ->
|
||||||
reverseEmbedderElementsMap[guestInstanceId] = key
|
reverseEmbedderElementsMap[guestInstanceId] = key
|
||||||
|
|
||||||
# Destroy an existing guest instance.
|
# Destroy an existing guest instance.
|
||||||
destroyGuest = (id) ->
|
destroyGuest = (embedder, id) ->
|
||||||
webViewManager.removeGuest id
|
webViewManager.removeGuest embedder, id
|
||||||
guestInstances[id].guest.destroy()
|
guestInstances[id].guest.destroy()
|
||||||
delete guestInstances[id]
|
delete guestInstances[id]
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', (event, elementInstanceId,
|
||||||
attachGuest event.sender, elementInstanceId, guestInstanceId, params
|
attachGuest event.sender, elementInstanceId, guestInstanceId, params
|
||||||
|
|
||||||
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', (event, id) ->
|
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', (event, id) ->
|
||||||
destroyGuest id
|
destroyGuest event.sender, id
|
||||||
|
|
||||||
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_AUTO_SIZE', (event, id, params) ->
|
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_AUTO_SIZE', (event, id, params) ->
|
||||||
guestInstances[id]?.guest.setAutoSize params.enableAutoSize, params.min, params.max
|
guestInstances[id]?.guest.setAutoSize params.enableAutoSize, params.min, params.max
|
||||||
|
|
|
@ -1,154 +0,0 @@
|
||||||
// Copyright (c) 2014 GitHub, Inc.
|
|
||||||
// Use of this source code is governed by the MIT license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#include "atom/browser/web_view/web_view_manager.h"
|
|
||||||
|
|
||||||
#include "atom/browser/api/atom_api_web_contents.h"
|
|
||||||
#include "atom/browser/atom_browser_context.h"
|
|
||||||
#include "atom/browser/web_view/web_view_renderer_state.h"
|
|
||||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
|
||||||
#include "base/bind.h"
|
|
||||||
#include "base/stl_util.h"
|
|
||||||
#include "content/public/browser/browser_thread.h"
|
|
||||||
#include "content/public/browser/render_process_host.h"
|
|
||||||
#include "native_mate/dictionary.h"
|
|
||||||
#include "native_mate/object_template_builder.h"
|
|
||||||
#include "net/base/filename_util.h"
|
|
||||||
|
|
||||||
#include "atom/common/node_includes.h"
|
|
||||||
|
|
||||||
namespace mate {
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct Converter<content::WebContents*> {
|
|
||||||
static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
|
|
||||||
content::WebContents** out) {
|
|
||||||
atom::api::WebContents* contents;
|
|
||||||
if (!Converter<atom::api::WebContents*>::FromV8(isolate, val, &contents))
|
|
||||||
return false;
|
|
||||||
*out = contents->web_contents();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct Converter<atom::WebViewManager::WebViewOptions> {
|
|
||||||
static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
|
|
||||||
atom::WebViewManager::WebViewOptions* out) {
|
|
||||||
Dictionary options;
|
|
||||||
if (!ConvertFromV8(isolate, val, &options))
|
|
||||||
return false;
|
|
||||||
return options.Get("nodeIntegration", &(out->node_integration)) &&
|
|
||||||
options.Get("plugins", &(out->plugins)) &&
|
|
||||||
options.Get("preloadUrl", &(out->preload_url)) &&
|
|
||||||
options.Get("disableWebSecurity", &(out->disable_web_security));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace mate
|
|
||||||
|
|
||||||
namespace atom {
|
|
||||||
|
|
||||||
WebViewManager::WebViewManager(content::BrowserContext* context) {
|
|
||||||
}
|
|
||||||
|
|
||||||
WebViewManager::~WebViewManager() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebViewManager::AddGuest(int guest_instance_id,
|
|
||||||
int element_instance_id,
|
|
||||||
content::WebContents* embedder,
|
|
||||||
content::WebContents* web_contents,
|
|
||||||
const WebViewOptions& options) {
|
|
||||||
web_contents_map_[guest_instance_id] = { web_contents, embedder };
|
|
||||||
|
|
||||||
WebViewRendererState::WebViewInfo web_view_info = {
|
|
||||||
guest_instance_id,
|
|
||||||
embedder,
|
|
||||||
options.node_integration,
|
|
||||||
options.plugins,
|
|
||||||
options.disable_web_security,
|
|
||||||
};
|
|
||||||
net::FileURLToFilePath(options.preload_url, &web_view_info.preload_script);
|
|
||||||
content::BrowserThread::PostTask(
|
|
||||||
content::BrowserThread::IO,
|
|
||||||
FROM_HERE,
|
|
||||||
base::Bind(&WebViewRendererState::AddGuest,
|
|
||||||
base::Unretained(WebViewRendererState::GetInstance()),
|
|
||||||
web_contents->GetRenderProcessHost()->GetID(),
|
|
||||||
web_view_info));
|
|
||||||
|
|
||||||
// Map the element in embedder to guest.
|
|
||||||
ElementInstanceKey key(embedder, element_instance_id);
|
|
||||||
element_instance_id_to_guest_map_[key] = guest_instance_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebViewManager::RemoveGuest(int guest_instance_id) {
|
|
||||||
if (!ContainsKey(web_contents_map_, guest_instance_id)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto web_contents = web_contents_map_[guest_instance_id].web_contents;
|
|
||||||
|
|
||||||
content::BrowserThread::PostTask(
|
|
||||||
content::BrowserThread::IO, FROM_HERE,
|
|
||||||
base::Bind(
|
|
||||||
&WebViewRendererState::RemoveGuest,
|
|
||||||
base::Unretained(WebViewRendererState::GetInstance()),
|
|
||||||
web_contents->GetRenderProcessHost()->GetID()));
|
|
||||||
|
|
||||||
web_contents_map_.erase(guest_instance_id);
|
|
||||||
|
|
||||||
// Remove the record of element in embedder too.
|
|
||||||
for (const auto& element : element_instance_id_to_guest_map_)
|
|
||||||
if (element.second == guest_instance_id) {
|
|
||||||
element_instance_id_to_guest_map_.erase(element.first);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
content::WebContents* WebViewManager::GetGuestByInstanceID(
|
|
||||||
content::WebContents* embedder,
|
|
||||||
int element_instance_id) {
|
|
||||||
ElementInstanceKey key(embedder, element_instance_id);
|
|
||||||
if (!ContainsKey(element_instance_id_to_guest_map_, key))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
int guest_instance_id = element_instance_id_to_guest_map_[key];
|
|
||||||
if (ContainsKey(web_contents_map_, guest_instance_id))
|
|
||||||
return web_contents_map_[guest_instance_id].web_contents;
|
|
||||||
else
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WebViewManager::ForEachGuest(content::WebContents* embedder_web_contents,
|
|
||||||
const GuestCallback& callback) {
|
|
||||||
for (auto& item : web_contents_map_)
|
|
||||||
if (item.second.embedder == embedder_web_contents &&
|
|
||||||
callback.Run(item.second.web_contents))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace atom
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
void Initialize(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> unused,
|
|
||||||
v8::Handle<v8::Context> context, void* priv) {
|
|
||||||
using atom::WebViewManager;
|
|
||||||
auto manager = static_cast<WebViewManager*>(
|
|
||||||
atom::AtomBrowserContext::Get()->GetGuestManager());
|
|
||||||
mate::Dictionary dict(context->GetIsolate(), exports);
|
|
||||||
dict.SetMethod("addGuest",
|
|
||||||
base::Bind(&WebViewManager::AddGuest,
|
|
||||||
base::Unretained(manager)));
|
|
||||||
dict.SetMethod("removeGuest",
|
|
||||||
base::Bind(&WebViewManager::RemoveGuest,
|
|
||||||
base::Unretained(manager)));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_web_view_manager, Initialize)
|
|
|
@ -1,46 +0,0 @@
|
||||||
// Copyright (c) 2014 GitHub, Inc.
|
|
||||||
// Use of this source code is governed by the MIT license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#include "atom/browser/web_view/web_view_renderer_state.h"
|
|
||||||
|
|
||||||
#include "content/public/browser/browser_thread.h"
|
|
||||||
|
|
||||||
namespace atom {
|
|
||||||
|
|
||||||
// static
|
|
||||||
WebViewRendererState* WebViewRendererState::GetInstance() {
|
|
||||||
return Singleton<WebViewRendererState>::get();
|
|
||||||
}
|
|
||||||
|
|
||||||
WebViewRendererState::WebViewRendererState() {
|
|
||||||
}
|
|
||||||
|
|
||||||
WebViewRendererState::~WebViewRendererState() {
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WebViewRendererState::IsGuest(int render_process_id) {
|
|
||||||
return webview_info_map_.find(render_process_id) !=
|
|
||||||
webview_info_map_.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebViewRendererState::AddGuest(int guest_process_id,
|
|
||||||
const WebViewInfo& webview_info) {
|
|
||||||
webview_info_map_[guest_process_id] = webview_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebViewRendererState::RemoveGuest(int guest_process_id) {
|
|
||||||
webview_info_map_.erase(guest_process_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WebViewRendererState::GetInfo(int guest_process_id,
|
|
||||||
WebViewInfo* webview_info) {
|
|
||||||
WebViewInfoMap::iterator iter = webview_info_map_.find(guest_process_id);
|
|
||||||
if (iter != webview_info_map_.end()) {
|
|
||||||
*webview_info = iter->second;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace atom
|
|
|
@ -1,65 +0,0 @@
|
||||||
// Copyright (c) 2014 GitHub, Inc.
|
|
||||||
// Use of this source code is governed by the MIT license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#ifndef ATOM_BROWSER_WEB_VIEW_WEB_VIEW_RENDERER_STATE_H_
|
|
||||||
#define ATOM_BROWSER_WEB_VIEW_WEB_VIEW_RENDERER_STATE_H_
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include "base/files/file_path.h"
|
|
||||||
#include "base/memory/singleton.h"
|
|
||||||
|
|
||||||
namespace content {
|
|
||||||
class WebContents;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace atom {
|
|
||||||
|
|
||||||
class WebViewManager;
|
|
||||||
|
|
||||||
// This class keeps track of <webview> renderer state for use on the IO thread.
|
|
||||||
// All methods should be called on the IO thread.
|
|
||||||
class WebViewRendererState {
|
|
||||||
public:
|
|
||||||
struct WebViewInfo {
|
|
||||||
int guest_instance_id;
|
|
||||||
content::WebContents* embedder;
|
|
||||||
bool node_integration;
|
|
||||||
bool plugins;
|
|
||||||
bool disable_web_security;
|
|
||||||
base::FilePath preload_script;
|
|
||||||
};
|
|
||||||
|
|
||||||
static WebViewRendererState* GetInstance();
|
|
||||||
|
|
||||||
// Looks up the information for the embedder <webview> for a given render
|
|
||||||
// view, if one exists. Called on the IO thread.
|
|
||||||
bool GetInfo(int guest_process_id, WebViewInfo* webview_info);
|
|
||||||
|
|
||||||
// Returns true if the given renderer is used by webviews.
|
|
||||||
bool IsGuest(int render_process_id);
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class WebViewManager;
|
|
||||||
friend struct DefaultSingletonTraits<WebViewRendererState>;
|
|
||||||
|
|
||||||
typedef std::map<int, WebViewInfo> WebViewInfoMap;
|
|
||||||
|
|
||||||
WebViewRendererState();
|
|
||||||
~WebViewRendererState();
|
|
||||||
|
|
||||||
// Adds or removes a <webview> guest render process from the set.
|
|
||||||
void AddGuest(int render_process_id, const WebViewInfo& webview_info);
|
|
||||||
void RemoveGuest(int render_process_id);
|
|
||||||
|
|
||||||
WebViewInfoMap webview_info_map_;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(WebViewRendererState);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace atom
|
|
||||||
|
|
||||||
#endif // ATOM_BROWSER_WEB_VIEW_WEB_VIEW_RENDERER_STATE_H_
|
|
101
atom/browser/web_view_manager.cc
Normal file
101
atom/browser/web_view_manager.cc
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
// Copyright (c) 2014 GitHub, Inc.
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "atom/browser/web_view_manager.h"
|
||||||
|
|
||||||
|
#include "atom/browser/atom_browser_context.h"
|
||||||
|
#include "content/public/browser/render_process_host.h"
|
||||||
|
#include "content/public/browser/web_contents.h"
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
// static
|
||||||
|
bool WebViewManager::GetInfoForProcess(content::RenderProcessHost* process,
|
||||||
|
WebViewInfo* info) {
|
||||||
|
if (!process)
|
||||||
|
return false;
|
||||||
|
auto context = process->GetBrowserContext();
|
||||||
|
if (!context)
|
||||||
|
return false;
|
||||||
|
auto manager = context->GetGuestManager();
|
||||||
|
if (!manager)
|
||||||
|
return false;
|
||||||
|
return static_cast<WebViewManager*>(manager)->GetInfo(process->GetID(), info);
|
||||||
|
}
|
||||||
|
|
||||||
|
WebViewManager::WebViewManager(content::BrowserContext* context) {
|
||||||
|
}
|
||||||
|
|
||||||
|
WebViewManager::~WebViewManager() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebViewManager::AddGuest(int guest_instance_id,
|
||||||
|
int element_instance_id,
|
||||||
|
content::WebContents* embedder,
|
||||||
|
content::WebContents* web_contents,
|
||||||
|
const WebViewInfo& info) {
|
||||||
|
base::AutoLock auto_lock(lock_);
|
||||||
|
web_contents_embdder_map_[guest_instance_id] = { web_contents, embedder };
|
||||||
|
|
||||||
|
int guest_process_id = web_contents->GetRenderProcessHost()->GetID();
|
||||||
|
webview_info_map_[guest_process_id] = info;
|
||||||
|
|
||||||
|
// Map the element in embedder to guest.
|
||||||
|
ElementInstanceKey key(embedder, element_instance_id);
|
||||||
|
element_instance_id_to_guest_map_[key] = guest_instance_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebViewManager::RemoveGuest(int guest_instance_id) {
|
||||||
|
base::AutoLock auto_lock(lock_);
|
||||||
|
if (!ContainsKey(web_contents_embdder_map_, guest_instance_id))
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto web_contents = web_contents_embdder_map_[guest_instance_id].web_contents;
|
||||||
|
web_contents_embdder_map_.erase(guest_instance_id);
|
||||||
|
|
||||||
|
int guest_process_id = web_contents->GetRenderProcessHost()->GetID();
|
||||||
|
webview_info_map_.erase(guest_process_id);
|
||||||
|
|
||||||
|
// Remove the record of element in embedder too.
|
||||||
|
for (const auto& element : element_instance_id_to_guest_map_)
|
||||||
|
if (element.second == guest_instance_id) {
|
||||||
|
element_instance_id_to_guest_map_.erase(element.first);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebViewManager::GetInfo(int guest_process_id, WebViewInfo* webview_info) {
|
||||||
|
base::AutoLock auto_lock(lock_);
|
||||||
|
WebViewInfoMap::iterator iter = webview_info_map_.find(guest_process_id);
|
||||||
|
if (iter != webview_info_map_.end()) {
|
||||||
|
*webview_info = iter->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
content::WebContents* WebViewManager::GetGuestByInstanceID(
|
||||||
|
content::WebContents* embedder,
|
||||||
|
int element_instance_id) {
|
||||||
|
ElementInstanceKey key(embedder, element_instance_id);
|
||||||
|
if (!ContainsKey(element_instance_id_to_guest_map_, key))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
int guest_instance_id = element_instance_id_to_guest_map_[key];
|
||||||
|
if (ContainsKey(web_contents_embdder_map_, guest_instance_id))
|
||||||
|
return web_contents_embdder_map_[guest_instance_id].web_contents;
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebViewManager::ForEachGuest(content::WebContents* embedder_web_contents,
|
||||||
|
const GuestCallback& callback) {
|
||||||
|
for (auto& item : web_contents_embdder_map_)
|
||||||
|
if (item.second.embedder == embedder_web_contents &&
|
||||||
|
callback.Run(item.second.web_contents))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace atom
|
|
@ -2,39 +2,52 @@
|
||||||
// Use of this source code is governed by the MIT license that can be
|
// Use of this source code is governed by the MIT license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#ifndef ATOM_BROWSER_WEB_VIEW_WEB_VIEW_MANAGER_H_
|
#ifndef ATOM_BROWSER_WEB_VIEW_MANAGER_H_
|
||||||
#define ATOM_BROWSER_WEB_VIEW_WEB_VIEW_MANAGER_H_
|
#define ATOM_BROWSER_WEB_VIEW_MANAGER_H_
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include "base/files/file_path.h"
|
||||||
|
#include "base/synchronization/lock.h"
|
||||||
#include "content/public/browser/browser_plugin_guest_manager.h"
|
#include "content/public/browser/browser_plugin_guest_manager.h"
|
||||||
#include "url/gurl.h"
|
|
||||||
|
|
||||||
namespace content {
|
namespace content {
|
||||||
class BrowserContext;
|
class BrowserContext;
|
||||||
|
class RenderProcessHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
class WebViewManager : public content::BrowserPluginGuestManager {
|
class WebViewManager : public content::BrowserPluginGuestManager {
|
||||||
public:
|
public:
|
||||||
explicit WebViewManager(content::BrowserContext* context);
|
struct WebViewInfo {
|
||||||
virtual ~WebViewManager();
|
int guest_instance_id;
|
||||||
|
content::WebContents* embedder;
|
||||||
struct WebViewOptions {
|
|
||||||
bool node_integration;
|
bool node_integration;
|
||||||
bool plugins;
|
bool plugins;
|
||||||
bool disable_web_security;
|
bool disable_web_security;
|
||||||
GURL preload_url;
|
base::FilePath preload_script;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Finds the WebViewManager attached with |process| and returns the
|
||||||
|
// WebViewInfo of it.
|
||||||
|
static bool GetInfoForProcess(content::RenderProcessHost* process,
|
||||||
|
WebViewInfo* info);
|
||||||
|
|
||||||
|
explicit WebViewManager(content::BrowserContext* context);
|
||||||
|
virtual ~WebViewManager();
|
||||||
|
|
||||||
void AddGuest(int guest_instance_id,
|
void AddGuest(int guest_instance_id,
|
||||||
int element_instance_id,
|
int element_instance_id,
|
||||||
content::WebContents* embedder,
|
content::WebContents* embedder,
|
||||||
content::WebContents* web_contents,
|
content::WebContents* web_contents,
|
||||||
const WebViewOptions& options);
|
const WebViewInfo& info);
|
||||||
void RemoveGuest(int guest_instance_id);
|
void RemoveGuest(int guest_instance_id);
|
||||||
|
|
||||||
|
// Looks up the information for the embedder <webview> for a given render
|
||||||
|
// view, if one exists. Called on the IO thread.
|
||||||
|
bool GetInfo(int guest_process_id, WebViewInfo* webview_info);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// content::BrowserPluginGuestManager:
|
// content::BrowserPluginGuestManager:
|
||||||
content::WebContents* GetGuestByInstanceID(
|
content::WebContents* GetGuestByInstanceID(
|
||||||
|
@ -45,19 +58,16 @@ class WebViewManager : public content::BrowserPluginGuestManager {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct WebContentsWithEmbedder {
|
struct WebContentsWithEmbedder {
|
||||||
content::WebContents* web_contents; // Weak ref.
|
content::WebContents* web_contents;
|
||||||
content::WebContents* embedder;
|
content::WebContents* embedder;
|
||||||
};
|
};
|
||||||
std::map<int, WebContentsWithEmbedder> web_contents_map_;
|
// guest_instance_id => (web_contents, embedder)
|
||||||
|
std::map<int, WebContentsWithEmbedder> web_contents_embdder_map_;
|
||||||
|
|
||||||
struct ElementInstanceKey {
|
struct ElementInstanceKey {
|
||||||
content::WebContents* owner_web_contents;
|
content::WebContents* owner_web_contents;
|
||||||
int element_instance_id;
|
int element_instance_id;
|
||||||
|
|
||||||
ElementInstanceKey()
|
|
||||||
: owner_web_contents(nullptr),
|
|
||||||
element_instance_id(0) {}
|
|
||||||
|
|
||||||
ElementInstanceKey(content::WebContents* owner_web_contents,
|
ElementInstanceKey(content::WebContents* owner_web_contents,
|
||||||
int element_instance_id)
|
int element_instance_id)
|
||||||
: owner_web_contents(owner_web_contents),
|
: owner_web_contents(owner_web_contents),
|
||||||
|
@ -74,11 +84,18 @@ class WebViewManager : public content::BrowserPluginGuestManager {
|
||||||
(element_instance_id == other.element_instance_id);
|
(element_instance_id == other.element_instance_id);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// (web_contents, element_instance_id) => guest_instance_id
|
||||||
std::map<ElementInstanceKey, int> element_instance_id_to_guest_map_;
|
std::map<ElementInstanceKey, int> element_instance_id_to_guest_map_;
|
||||||
|
|
||||||
|
typedef std::map<int, WebViewInfo> WebViewInfoMap;
|
||||||
|
// guest_process_id => (guest_instance_id, embedder, ...)
|
||||||
|
WebViewInfoMap webview_info_map_;
|
||||||
|
|
||||||
|
base::Lock lock_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(WebViewManager);
|
DISALLOW_COPY_AND_ASSIGN(WebViewManager);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace atom
|
} // namespace atom
|
||||||
|
|
||||||
#endif // ATOM_BROWSER_WEB_VIEW_WEB_VIEW_MANAGER_H_
|
#endif // ATOM_BROWSER_WEB_VIEW_MANAGER_H_
|
|
@ -66,6 +66,7 @@ REFERENCE_MODULE(atom_browser_protocol);
|
||||||
REFERENCE_MODULE(atom_browser_global_shortcut);
|
REFERENCE_MODULE(atom_browser_global_shortcut);
|
||||||
REFERENCE_MODULE(atom_browser_tray);
|
REFERENCE_MODULE(atom_browser_tray);
|
||||||
REFERENCE_MODULE(atom_browser_web_contents);
|
REFERENCE_MODULE(atom_browser_web_contents);
|
||||||
|
REFERENCE_MODULE(atom_browser_web_view_manager);
|
||||||
REFERENCE_MODULE(atom_browser_window);
|
REFERENCE_MODULE(atom_browser_window);
|
||||||
REFERENCE_MODULE(atom_common_asar);
|
REFERENCE_MODULE(atom_common_asar);
|
||||||
REFERENCE_MODULE(atom_common_clipboard);
|
REFERENCE_MODULE(atom_common_clipboard);
|
||||||
|
|
Loading…
Reference in a new issue