Merge pull request #6035 from electron/content-scripts-in-web-views
Load content scripts in webview devtools
This commit is contained in:
commit
efa667fa0a
6 changed files with 73 additions and 41 deletions
|
@ -4,9 +4,8 @@
|
|||
|
||||
#include "atom/browser/api/atom_api_render_process_preferences.h"
|
||||
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
|
@ -19,18 +18,17 @@ namespace api {
|
|||
|
||||
namespace {
|
||||
|
||||
bool IsBrowserWindow(content::RenderProcessHost* process) {
|
||||
bool IsWebContents(v8::Isolate* isolate, content::RenderProcessHost* process) {
|
||||
content::WebContents* web_contents =
|
||||
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->
|
||||
GetWebContentsFromProcessID(process->GetID());
|
||||
if (!web_contents)
|
||||
return false;
|
||||
|
||||
NativeWindow* window = NativeWindow::FromWebContents(web_contents);
|
||||
if (!window)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
auto api_web_contents = WebContents::CreateFrom(isolate, web_contents);
|
||||
auto type = api_web_contents->GetType();
|
||||
return type == WebContents::Type::BROWSER_WINDOW ||
|
||||
type == WebContents::Type::WEB_VIEW;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -63,10 +61,11 @@ void RenderProcessPreferences::BuildPrototype(
|
|||
|
||||
// static
|
||||
mate::Handle<RenderProcessPreferences>
|
||||
RenderProcessPreferences::ForAllBrowserWindow(v8::Isolate* isolate) {
|
||||
RenderProcessPreferences::ForAllWebContents(v8::Isolate* isolate) {
|
||||
return mate::CreateHandle(
|
||||
isolate,
|
||||
new RenderProcessPreferences(isolate, base::Bind(&IsBrowserWindow)));
|
||||
new RenderProcessPreferences(isolate,
|
||||
base::Bind(&IsWebContents, isolate)));
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
@ -78,8 +77,8 @@ namespace {
|
|||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
mate::Dictionary dict(context->GetIsolate(), exports);
|
||||
dict.SetMethod("forAllBrowserWindow",
|
||||
&atom::api::RenderProcessPreferences::ForAllBrowserWindow);
|
||||
dict.SetMethod("forAllWebContents",
|
||||
&atom::api::RenderProcessPreferences::ForAllWebContents);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -17,7 +17,7 @@ class RenderProcessPreferences
|
|||
: public mate::Wrappable<RenderProcessPreferences> {
|
||||
public:
|
||||
static mate::Handle<RenderProcessPreferences>
|
||||
ForAllBrowserWindow(v8::Isolate* isolate);
|
||||
ForAllWebContents(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::ObjectTemplate> prototype);
|
||||
|
|
|
@ -187,6 +187,39 @@ struct Converter<content::SavePageType> {
|
|||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<atom::api::WebContents::Type> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
atom::api::WebContents::Type val) {
|
||||
using Type = atom::api::WebContents::Type;
|
||||
std::string type = "";
|
||||
switch (val) {
|
||||
case Type::BACKGROUND_PAGE: type = "backgroundPage"; break;
|
||||
case Type::BROWSER_WINDOW: type = "window"; break;
|
||||
case Type::REMOTE: type = "remote"; break;
|
||||
case Type::WEB_VIEW: type = "webview"; break;
|
||||
default: break;
|
||||
}
|
||||
return mate::ConvertToV8(isolate, type);
|
||||
}
|
||||
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
atom::api::WebContents::Type* out) {
|
||||
using Type = atom::api::WebContents::Type;
|
||||
std::string type;
|
||||
if (!ConvertFromV8(isolate, val, &type))
|
||||
return false;
|
||||
if (type == "webview") {
|
||||
*out = Type::WEB_VIEW;
|
||||
} else if (type == "backgroundPage") {
|
||||
*out = Type::BACKGROUND_PAGE;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
|
||||
|
@ -238,10 +271,8 @@ WebContents::WebContents(v8::Isolate* isolate,
|
|||
// Read options.
|
||||
options.Get("backgroundThrottling", &background_throttling_);
|
||||
|
||||
// Whether it is a guest WebContents.
|
||||
bool is_guest = false;
|
||||
options.Get("isGuest", &is_guest);
|
||||
type_ = is_guest ? WEB_VIEW : BROWSER_WINDOW;
|
||||
type_ = BROWSER_WINDOW;
|
||||
options.Get("type", &type_);
|
||||
|
||||
// Obtain the session.
|
||||
std::string partition;
|
||||
|
@ -261,7 +292,7 @@ WebContents::WebContents(v8::Isolate* isolate,
|
|||
session_.Reset(isolate, session.ToV8());
|
||||
|
||||
content::WebContents* web_contents;
|
||||
if (is_guest) {
|
||||
if (IsGuest()) {
|
||||
scoped_refptr<content::SiteInstance> site_instance =
|
||||
content::SiteInstance::CreateForURL(
|
||||
session->browser_context(), GURL("chrome-guest://fake-host"));
|
||||
|
@ -290,7 +321,7 @@ WebContents::WebContents(v8::Isolate* isolate,
|
|||
|
||||
web_contents->SetUserAgentOverride(GetBrowserContext()->GetUserAgent());
|
||||
|
||||
if (is_guest) {
|
||||
if (IsGuest()) {
|
||||
guest_delegate_->Initialize(this);
|
||||
|
||||
NativeWindow* owner_window = nullptr;
|
||||
|
@ -744,13 +775,8 @@ int WebContents::GetID() const {
|
|||
return web_contents()->GetRenderProcessHost()->GetID();
|
||||
}
|
||||
|
||||
std::string WebContents::GetType() const {
|
||||
switch (type_) {
|
||||
case BROWSER_WINDOW: return "window";
|
||||
case WEB_VIEW: return "webview";
|
||||
case REMOTE: return "remote";
|
||||
default: return "";
|
||||
}
|
||||
WebContents::Type WebContents::GetType() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
bool WebContents::Equal(const WebContents* web_contents) const {
|
||||
|
|
|
@ -43,6 +43,13 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
|||
public CommonWebContentsDelegate,
|
||||
public content::WebContentsObserver {
|
||||
public:
|
||||
enum Type {
|
||||
BACKGROUND_PAGE, // A DevTools extension background page.
|
||||
BROWSER_WINDOW, // Used by BrowserWindow.
|
||||
REMOTE, // Thin wrap around an existing WebContents.
|
||||
WEB_VIEW, // Used by <webview>.
|
||||
};
|
||||
|
||||
// For node.js callback function type: function(error, buffer)
|
||||
using PrintToPDFCallback =
|
||||
base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>)>;
|
||||
|
@ -59,7 +66,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
|||
v8::Local<v8::ObjectTemplate> prototype);
|
||||
|
||||
int GetID() const;
|
||||
std::string GetType() const;
|
||||
Type GetType() const;
|
||||
bool Equal(const WebContents* web_contents) const;
|
||||
void LoadURL(const GURL& url, const mate::Dictionary& options);
|
||||
void DownloadURL(const GURL& url);
|
||||
|
@ -268,12 +275,6 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
|||
void DevToolsClosed() override;
|
||||
|
||||
private:
|
||||
enum Type {
|
||||
BROWSER_WINDOW, // Used by BrowserWindow.
|
||||
WEB_VIEW, // Used by <webview>.
|
||||
REMOTE, // Thin wrap around an existing WebContents.
|
||||
};
|
||||
|
||||
AtomBrowserContext* GetBrowserContext() const;
|
||||
|
||||
uint32_t GetNextRequestId() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const {app, ipcMain, session, webContents, BrowserWindow} = require('electron')
|
||||
const {getAllWebContents} = process.atomBinding('web_contents')
|
||||
const renderProcessPreferences = process.atomBinding('render_process_preferences').forAllBrowserWindow()
|
||||
const renderProcessPreferences = process.atomBinding('render_process_preferences').forAllWebContents()
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
@ -19,6 +19,11 @@ const generateExtensionIdFromName = function (name) {
|
|||
return name.replace(/[\W_]+/g, '-').toLowerCase()
|
||||
}
|
||||
|
||||
const isWindowOrWebView = function (webContents) {
|
||||
const type = webContents.getType()
|
||||
return type === 'window' || type === 'webview'
|
||||
}
|
||||
|
||||
// Create or get manifest object from |srcDirectory|.
|
||||
const getManifestFromPath = function (srcDirectory) {
|
||||
let manifest
|
||||
|
@ -73,6 +78,7 @@ const startBackgroundPages = function (manifest) {
|
|||
const html = new Buffer(`<html><body>${scripts}</body></html>`)
|
||||
|
||||
const contents = webContents.create({
|
||||
type: 'backgroundPage',
|
||||
commandLineSwitches: ['--background-page']
|
||||
})
|
||||
backgroundPages[manifest.extensionId] = { html: html, webContents: contents }
|
||||
|
@ -111,7 +117,7 @@ let nextId = 0
|
|||
ipcMain.on('CHROME_RUNTIME_CONNECT', function (event, extensionId, connectInfo) {
|
||||
const page = backgroundPages[extensionId]
|
||||
if (!page) {
|
||||
console.error(`Connect to unkown extension ${extensionId}`)
|
||||
console.error(`Connect to unknown extension ${extensionId}`)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -132,7 +138,7 @@ ipcMain.on('CHROME_I18N_MANIFEST', function (event, extensionId) {
|
|||
ipcMain.on('CHROME_RUNTIME_SENDMESSAGE', function (event, extensionId, message) {
|
||||
const page = backgroundPages[extensionId]
|
||||
if (!page) {
|
||||
console.error(`Connect to unkown extension ${extensionId}`)
|
||||
console.error(`Connect to unknown extension ${extensionId}`)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -142,7 +148,7 @@ ipcMain.on('CHROME_RUNTIME_SENDMESSAGE', function (event, extensionId, message)
|
|||
ipcMain.on('CHROME_TABS_SEND_MESSAGE', function (event, tabId, extensionId, isBackgroundPage, message) {
|
||||
const contents = webContents.fromId(tabId)
|
||||
if (!contents) {
|
||||
console.error(`Sending message to unkown tab ${tabId}`)
|
||||
console.error(`Sending message to unknown tab ${tabId}`)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -154,7 +160,7 @@ ipcMain.on('CHROME_TABS_SEND_MESSAGE', function (event, tabId, extensionId, isBa
|
|||
ipcMain.on('CHROME_TABS_EXECUTESCRIPT', function (event, requestId, tabId, extensionId, details) {
|
||||
const contents = webContents.fromId(tabId)
|
||||
if (!contents) {
|
||||
console.error(`Sending message to unkown tab ${tabId}`)
|
||||
console.error(`Sending message to unknown tab ${tabId}`)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -237,7 +243,7 @@ const loadDevToolsExtensions = function (win, manifests) {
|
|||
}
|
||||
|
||||
app.on('web-contents-created', function (event, webContents) {
|
||||
if (webContents.getType() === 'remote') return
|
||||
if (!isWindowOrWebView(webContents)) return
|
||||
|
||||
hookWebContentsForTabEvents(webContents)
|
||||
webContents.on('devtools-opened', function () {
|
||||
|
@ -322,7 +328,7 @@ app.once('ready', function () {
|
|||
const manifest = getManifestFromPath(srcDirectory)
|
||||
if (manifest) {
|
||||
for (const webContents of getAllWebContents()) {
|
||||
if (webContents.getType() !== 'remote') {
|
||||
if (isWindowOrWebView(webContents)) {
|
||||
loadDevToolsExtensions(webContents, [manifest])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ const createGuest = function (embedder, params) {
|
|||
|
||||
const id = getNextInstanceId(embedder)
|
||||
const guest = webContents.create({
|
||||
isGuest: true,
|
||||
type: 'webview',
|
||||
partition: params.partition,
|
||||
embedder: embedder
|
||||
})
|
||||
|
|
Loading…
Add table
Reference in a new issue