Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
4f682851
V
vscode
项目概览
xxadev
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
4f682851
编写于
10月 16, 2019
作者:
M
Matt Bierner
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Start trying to extract common webview code to base class
上级
1cbdd7ff
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
213 addition
and
213 deletion
+213
-213
src/vs/workbench/contrib/webview/browser/baseWebviewElement.ts
...s/workbench/contrib/webview/browser/baseWebviewElement.ts
+57
-0
src/vs/workbench/contrib/webview/browser/webviewElement.ts
src/vs/workbench/contrib/webview/browser/webviewElement.ts
+38
-81
src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts
...kbench/contrib/webview/electron-browser/webviewElement.ts
+118
-132
未找到文件。
src/vs/workbench/contrib/webview/browser/baseWebviewElement.ts
0 → 100644
浏览文件 @
4f682851
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
addClass
}
from
'
vs/base/browser/dom
'
;
import
{
Disposable
,
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
export
const
enum
WebviewMessageChannels
{
onmessage
=
'
onmessage
'
,
didClickLink
=
'
did-click-link
'
,
didScroll
=
'
did-scroll
'
,
didFocus
=
'
did-focus
'
,
didBlur
=
'
did-blur
'
,
doUpdateState
=
'
do-update-state
'
,
doReload
=
'
do-reload
'
,
loadResource
=
'
load-resource
'
,
loadLocalhost
=
'
load-localhost
'
,
webviewReady
=
'
webview-ready
'
,
}
export
abstract
class
BaseWebview
<
T
extends
HTMLElement
>
extends
Disposable
{
private
_element
:
T
|
undefined
;
protected
get
element
():
T
|
undefined
{
return
this
.
_element
;
}
protected
readonly
_ready
:
Promise
<
void
>
;
constructor
(
options
:
WebviewOptions
)
{
super
();
this
.
_element
=
this
.
createElement
(
options
);
this
.
_ready
=
new
Promise
(
resolve
=>
{
const
subscription
=
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
webviewReady
,
()
=>
{
if
(
this
.
element
)
{
addClass
(
this
.
element
,
'
ready
'
);
}
subscription
.
dispose
();
resolve
();
}));
});
}
protected
abstract
createElement
(
options
:
WebviewOptions
):
T
;
protected
abstract
on
<
T
=
unknown
>
(
channel
:
WebviewMessageChannels
,
handler
:
(
data
:
T
)
=>
void
):
IDisposable
;
dispose
():
void
{
if
(
this
.
element
)
{
this
.
element
.
remove
();
}
this
.
_element
=
undefined
;
super
.
dispose
();
}
}
src/vs/workbench/contrib/webview/browser/webviewElement.ts
浏览文件 @
4f682851
...
...
@@ -3,9 +3,9 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
add
Class
,
add
DisposableListener
}
from
'
vs/base/browser/dom
'
;
import
{
addDisposableListener
}
from
'
vs/base/browser/dom
'
;
import
{
Emitter
}
from
'
vs/base/common/event
'
;
import
{
Disposable
,
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
isWeb
}
from
'
vs/base/common/platform
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
...
...
@@ -18,6 +18,7 @@ import { WebviewPortMappingManager } from 'vs/workbench/contrib/webview/common/p
import
{
loadLocalResource
}
from
'
vs/workbench/contrib/webview/common/resourceLoader
'
;
import
{
WebviewThemeDataProvider
}
from
'
vs/workbench/contrib/webview/common/themeing
'
;
import
{
IWorkbenchEnvironmentService
}
from
'
vs/workbench/services/environment/common/environmentService
'
;
import
{
BaseWebview
,
WebviewMessageChannels
}
from
'
vs/workbench/contrib/webview/browser/baseWebviewElement
'
;
interface
WebviewContent
{
readonly
html
:
string
;
...
...
@@ -25,28 +26,7 @@ interface WebviewContent {
readonly
state
:
string
|
undefined
;
}
const
enum
WebviewMessageChannels
{
onmessage
=
'
onmessage
'
,
didClickLink
=
'
did-click-link
'
,
didScroll
=
'
did-scroll
'
,
didFocus
=
'
did-focus
'
,
didBlur
=
'
did-blur
'
,
doUpdateState
=
'
do-update-state
'
,
doReload
=
'
do-reload
'
,
loadResource
=
'
load-resource
'
,
loadLocalhost
=
'
load-localhost
'
,
webviewReady
=
'
webview-ready
'
,
}
interface
WebviewEventEmitter
{
on
(
channel
:
WebviewMessageChannels
,
handler
:
(
data
:
unknown
)
=>
void
):
IDisposable
;
}
export
class
IFrameWebview
extends
Disposable
implements
Webview
{
private
element
?:
HTMLIFrameElement
;
private
readonly
_ready
:
Promise
<
void
>
;
export
class
IFrameWebview
extends
BaseWebview
<
HTMLIFrameElement
>
implements
Webview
{
private
content
:
WebviewContent
;
private
_focused
=
false
;
...
...
@@ -54,8 +34,6 @@ export class IFrameWebview extends Disposable implements Webview {
public
extension
:
WebviewExtensionDescription
|
undefined
;
private
webviewEventEmitter
:
WebviewEventEmitter
;
constructor
(
private
readonly
id
:
string
,
options
:
WebviewOptions
,
...
...
@@ -66,7 +44,7 @@ export class IFrameWebview extends Disposable implements Webview {
@
IFileService
private
readonly
fileService
:
IFileService
,
@
IConfigurationService
private
readonly
_configurationService
:
IConfigurationService
,
)
{
super
();
super
(
options
);
if
(
!
this
.
useExternalEndpoint
&&
(
!
environmentService
.
options
||
typeof
environmentService
.
webviewExternalEndpoint
!==
'
string
'
))
{
throw
new
Error
(
'
To use iframe based webviews, you must configure `environmentService.webviewExternalEndpoint`
'
);
}
...
...
@@ -83,86 +61,65 @@ export class IFrameWebview extends Disposable implements Webview {
state
:
undefined
};
this
.
element
=
document
.
createElement
(
'
iframe
'
);
this
.
element
.
className
=
`webview
${
options
.
customClasses
}
`
;
this
.
element
.
sandbox
.
add
(
'
allow-scripts
'
,
'
allow-same-origin
'
);
this
.
element
.
setAttribute
(
'
src
'
,
`
${
this
.
externalEndpoint
}
/index.html?id=
${
this
.
id
}
`
);
this
.
element
.
style
.
border
=
'
none
'
;
this
.
element
.
style
.
width
=
'
100%
'
;
this
.
element
.
style
.
height
=
'
100%
'
;
this
.
webviewEventEmitter
=
{
on
:
(
channel
,
handler
)
=>
{
return
addDisposableListener
(
window
,
'
message
'
,
e
=>
{
if
(
!
e
||
!
e
.
data
||
e
.
data
.
target
!==
this
.
id
)
{
return
;
}
if
(
e
.
data
.
channel
===
channel
)
{
handler
(
e
.
data
.
data
);
}
});
}
};
this
.
_register
(
this
.
webviewEventEmitter
.
on
(
WebviewMessageChannels
.
onmessage
,
(
data
)
=>
{
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
onmessage
,
(
data
:
any
)
=>
{
this
.
_onMessage
.
fire
(
data
);
}));
this
.
_register
(
this
.
webviewEventEmitter
.
on
(
WebviewMessageChannels
.
didClickLink
,
(
uri
)
=>
{
if
(
typeof
uri
===
'
string
'
)
{
this
.
_onDidClickLink
.
fire
(
URI
.
parse
(
uri
));
}
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
didClickLink
,
(
uri
:
string
)
=>
{
this
.
_onDidClickLink
.
fire
(
URI
.
parse
(
uri
));
}));
this
.
_register
(
this
.
webviewEventEmitter
.
on
(
WebviewMessageChannels
.
didScroll
,
()
=>
{
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
didScroll
,
()
=>
{
// if (e.args && typeof e.args[0] === 'number') {
// this._onDidScroll.fire({ scrollYPercentage: e.args[0] });
// }
}));
this
.
_register
(
this
.
webviewEventEmitter
.
on
(
WebviewMessageChannels
.
doReload
,
()
=>
{
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
doReload
,
()
=>
{
this
.
reload
();
}));
this
.
_register
(
this
.
webviewEventEmitter
.
on
(
WebviewMessageChannels
.
doUpdateState
,
(
state
:
any
)
=>
{
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
doUpdateState
,
(
state
:
any
)
=>
{
this
.
state
=
state
;
this
.
_onDidUpdateState
.
fire
(
state
);
}));
this
.
_register
(
this
.
webviewEventEmitter
.
on
(
WebviewMessageChannels
.
didFocus
,
()
=>
{
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
didFocus
,
()
=>
{
this
.
handleFocusChange
(
true
);
}));
this
.
_register
(
this
.
webviewEventEmitter
.
on
(
WebviewMessageChannels
.
didBlur
,
()
=>
{
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
didBlur
,
()
=>
{
this
.
handleFocusChange
(
false
);
}));
this
.
_register
(
this
.
webviewEventEmitter
.
on
(
WebviewMessageChannels
.
loadResource
,
(
entry
:
any
)
=>
{
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
loadResource
,
(
entry
:
any
)
=>
{
const
rawPath
=
entry
.
path
;
const
normalizedPath
=
decodeURIComponent
(
rawPath
);
const
uri
=
URI
.
parse
(
normalizedPath
.
replace
(
/^
\/(\w
+
)\/(
.+
)
$/
,
(
_
,
scheme
,
path
)
=>
scheme
+
'
:/
'
+
path
));
this
.
loadResource
(
rawPath
,
uri
);
}));
this
.
_register
(
this
.
webviewEventEmitter
.
on
(
WebviewMessageChannels
.
loadLocalhost
,
(
entry
:
any
)
=>
{
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
loadLocalhost
,
(
entry
:
any
)
=>
{
this
.
localLocalhost
(
entry
.
origin
);
}));
this
.
_ready
=
new
Promise
(
resolve
=>
{
const
subscription
=
this
.
_register
(
this
.
webviewEventEmitter
.
on
(
WebviewMessageChannels
.
webviewReady
,
()
=>
{
if
(
this
.
element
)
{
addClass
(
this
.
element
,
'
ready
'
);
}
subscription
.
dispose
();
resolve
();
}));
});
this
.
style
();
this
.
_register
(
webviewThemeDataProvider
.
onThemeDataChanged
(
this
.
style
,
this
));
}
protected
createElement
(
options
:
WebviewOptions
)
{
const
element
=
document
.
createElement
(
'
iframe
'
);
element
.
className
=
`webview
${
options
.
customClasses
}
`
;
element
.
sandbox
.
add
(
'
allow-scripts
'
,
'
allow-same-origin
'
);
element
.
setAttribute
(
'
src
'
,
`
${
this
.
externalEndpoint
}
/index.html?id=
${
this
.
id
}
`
);
element
.
style
.
border
=
'
none
'
;
element
.
style
.
width
=
'
100%
'
;
element
.
style
.
height
=
'
100%
'
;
return
element
;
}
private
get
externalEndpoint
():
string
{
return
'
http://127.0.0.1:8080
'
;
const
endpoint
=
this
.
environmentService
.
webviewExternalEndpoint
!
.
replace
(
'
{{uuid}}
'
,
this
.
id
);
if
(
endpoint
[
endpoint
.
length
-
1
]
===
'
/
'
)
{
return
endpoint
.
slice
(
0
,
endpoint
.
length
-
1
);
...
...
@@ -255,17 +212,6 @@ export class IFrameWebview extends Disposable implements Webview {
}
}
dispose
():
void
{
if
(
this
.
element
)
{
if
(
this
.
element
.
parentElement
)
{
this
.
element
.
parentElement
.
removeChild
(
this
.
element
);
}
}
this
.
element
=
undefined
!
;
super
.
dispose
();
}
reload
():
void
{
this
.
doUpdateContent
();
}
...
...
@@ -339,4 +285,15 @@ export class IFrameWebview extends Disposable implements Webview {
location
:
redirect
});
}
protected
on
<
T
=
unknown
>
(
channel
:
WebviewMessageChannels
,
handler
:
(
data
:
T
)
=>
void
):
IDisposable
{
return
addDisposableListener
(
window
,
'
message
'
,
e
=>
{
if
(
!
e
||
!
e
.
data
||
e
.
data
.
target
!==
this
.
id
)
{
return
;
}
if
(
e
.
data
.
channel
===
channel
)
{
handler
(
e
.
data
.
data
);
}
});
}
}
src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts
浏览文件 @
4f682851
...
...
@@ -4,10 +4,10 @@
*--------------------------------------------------------------------------------------------*/
import
{
FindInPageOptions
,
OnBeforeRequestDetails
,
OnHeadersReceivedDetails
,
Response
,
WebContents
,
WebviewTag
}
from
'
electron
'
;
import
{
add
Class
,
add
DisposableListener
}
from
'
vs/base/browser/dom
'
;
import
{
addDisposableListener
}
from
'
vs/base/browser/dom
'
;
import
{
Emitter
,
Event
}
from
'
vs/base/common/event
'
;
import
{
once
}
from
'
vs/base/common/functional
'
;
import
{
Disposable
,
toDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
Disposable
,
toDisposable
,
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
isMacintosh
}
from
'
vs/base/common/platform
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
*
as
modes
from
'
vs/editor/common/modes
'
;
...
...
@@ -24,6 +24,7 @@ import { WebviewThemeDataProvider } from 'vs/workbench/contrib/webview/common/th
import
{
registerFileProtocol
}
from
'
vs/workbench/contrib/webview/electron-browser/webviewProtocols
'
;
import
{
WebviewFindDelegate
,
WebviewFindWidget
}
from
'
../browser/webviewFindWidget
'
;
import
{
areWebviewInputOptionsEqual
}
from
'
../browser/webviewWorkbenchService
'
;
import
{
BaseWebview
,
WebviewMessageChannels
}
from
'
vs/workbench/contrib/webview/browser/baseWebviewElement
'
;
interface
IKeydownEvent
{
key
:
string
;
...
...
@@ -233,10 +234,7 @@ interface WebviewContent {
readonly
state
:
string
|
undefined
;
}
export
class
ElectronWebviewBasedWebview
extends
Disposable
implements
Webview
,
WebviewFindDelegate
{
private
_webview
:
WebviewTag
|
undefined
;
private
_ready
:
Promise
<
void
>
;
export
class
ElectronWebviewBasedWebview
extends
BaseWebview
<
WebviewTag
>
implements
Webview
,
WebviewFindDelegate
{
private
_webviewFindWidget
:
WebviewFindWidget
|
undefined
;
private
_findStarted
:
boolean
=
false
;
private
content
:
WebviewContent
;
...
...
@@ -258,39 +256,15 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview,
@
ITelemetryService
private
readonly
_telemetryService
:
ITelemetryService
,
@
IEnvironmentService
private
readonly
_environementService
:
IEnvironmentService
,
)
{
super
();
super
(
options
);
this
.
content
=
{
html
:
''
,
options
:
contentOptions
,
state
:
undefined
};
this
.
_webview
=
document
.
createElement
(
'
webview
'
);
this
.
_webview
.
setAttribute
(
'
partition
'
,
`webview
${
Date
.
now
()}
`
);
this
.
_webview
.
setAttribute
(
'
webpreferences
'
,
'
contextIsolation=yes
'
);
this
.
_webview
.
className
=
`webview
${
options
.
customClasses
}
`
;
this
.
_webview
.
style
.
flex
=
'
0 1
'
;
this
.
_webview
.
style
.
width
=
'
0
'
;
this
.
_webview
.
style
.
height
=
'
0
'
;
this
.
_webview
.
style
.
outline
=
'
0
'
;
this
.
_webview
.
preload
=
require
.
toUrl
(
'
./pre/electron-index.js
'
);
this
.
_webview
.
src
=
'
data:text/html;charset=utf-8,%3C%21DOCTYPE%20html%3E%0D%0A%3Chtml%20lang%3D%22en%22%20style%3D%22width%3A%20100%25%3B%20height%3A%20100%25%22%3E%0D%0A%3Chead%3E%0D%0A%09%3Ctitle%3EVirtual%20Document%3C%2Ftitle%3E%0D%0A%3C%2Fhead%3E%0D%0A%3Cbody%20style%3D%22margin%3A%200%3B%20overflow%3A%20hidden%3B%20width%3A%20100%25%3B%20height%3A%20100%25%22%3E%0D%0A%3C%2Fbody%3E%0D%0A%3C%2Fhtml%3E
'
;
this
.
_ready
=
new
Promise
(
resolve
=>
{
const
subscription
=
this
.
_register
(
addDisposableListener
(
this
.
_webview
!
,
'
ipc-message
'
,
(
event
)
=>
{
if
(
this
.
_webview
&&
event
.
channel
===
'
webview-ready
'
)
{
// console.info('[PID Webview] ' event.args[0]);
addClass
(
this
.
_webview
,
'
ready
'
);
// can be found by debug command
subscription
.
dispose
();
resolve
();
}
}));
});
const
webviewAndContents
=
this
.
_register
(
new
WebviewTagHandle
(
this
.
_webview
));
const
webviewAndContents
=
this
.
_register
(
new
WebviewTagHandle
(
this
.
element
!
));
const
session
=
this
.
_register
(
new
WebviewSession
(
webviewAndContents
));
this
.
_register
(
new
WebviewProtocolProvider
(
...
...
@@ -308,97 +282,87 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview,
this
.
_register
(
new
WebviewKeyboardHandler
(
webviewAndContents
));
this
.
_register
(
addDisposableListener
(
this
.
_webview
,
'
console-message
'
,
function
(
e
:
{
level
:
number
;
message
:
string
;
line
:
number
;
sourceId
:
string
;
})
{
this
.
_register
(
addDisposableListener
(
this
.
element
!
,
'
console-message
'
,
function
(
e
:
{
level
:
number
;
message
:
string
;
line
:
number
;
sourceId
:
string
;
})
{
console
.
log
(
`[Embedded Page]
${
e
.
message
}
`
);
}));
this
.
_register
(
addDisposableListener
(
this
.
_webview
,
'
dom-ready
'
,
()
=>
{
this
.
_register
(
addDisposableListener
(
this
.
element
!
,
'
dom-ready
'
,
()
=>
{
// Workaround for https://github.com/electron/electron/issues/14474
if
(
this
.
_webview
&&
(
this
.
_focused
||
document
.
activeElement
===
this
.
_webview
))
{
this
.
_webview
.
blur
();
this
.
_webview
.
focus
();
if
(
this
.
element
&&
(
this
.
_focused
||
document
.
activeElement
===
this
.
element
))
{
this
.
element
.
blur
();
this
.
element
.
focus
();
}
}));
this
.
_register
(
addDisposableListener
(
this
.
_webview
,
'
crashed
'
,
()
=>
{
this
.
_register
(
addDisposableListener
(
this
.
element
!
,
'
crashed
'
,
()
=>
{
console
.
error
(
'
embedded page crashed
'
);
}));
this
.
_register
(
addDisposableListener
(
this
.
_webview
,
'
ipc-message
'
,
(
event
)
=>
{
if
(
!
this
.
_webview
)
{
return
;
}
switch
(
event
.
channel
)
{
case
'
onmessage
'
:
if
(
event
.
args
&&
event
.
args
.
length
)
{
this
.
_onMessage
.
fire
(
event
.
args
[
0
]);
}
return
;
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
onmessage
,
(
data
:
any
)
=>
{
this
.
_onMessage
.
fire
(
data
);
}));
case
'
did-click-link
'
:
const
[
uri
]
=
event
.
args
;
this
.
_onDidClickLink
.
fire
(
URI
.
parse
(
uri
));
return
;
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
didClickLink
,
(
uri
:
string
)
=>
{
this
.
_onDidClickLink
.
fire
(
URI
.
parse
(
uri
));
}));
case
'
synthetic-mouse-event
'
:
{
const
rawEvent
=
event
.
args
[
0
];
const
bounds
=
this
.
_webview
.
getBoundingClientRect
();
try
{
window
.
dispatchEvent
(
new
MouseEvent
(
rawEvent
.
type
,
{
...
rawEvent
,
clientX
:
rawEvent
.
clientX
+
bounds
.
left
,
clientY
:
rawEvent
.
clientY
+
bounds
.
top
,
}));
return
;
}
catch
{
// CustomEvent was treated as MouseEvent so don't do anything - https://github.com/microsoft/vscode/issues/78915
return
;
}
}
this
.
_register
(
this
.
on
(
'
synthetic-mouse-event
'
,
(
rawEvent
:
any
)
=>
{
if
(
!
this
.
element
)
{
return
;
}
const
bounds
=
this
.
element
.
getBoundingClientRect
();
try
{
window
.
dispatchEvent
(
new
MouseEvent
(
rawEvent
.
type
,
{
...
rawEvent
,
clientX
:
rawEvent
.
clientX
+
bounds
.
left
,
clientY
:
rawEvent
.
clientY
+
bounds
.
top
,
}));
return
;
}
catch
{
// CustomEvent was treated as MouseEvent so don't do anything - https://github.com/microsoft/vscode/issues/78915
return
;
}
}));
case
'
did-set-content
'
:
this
.
_webview
.
style
.
flex
=
''
;
this
.
_webview
.
style
.
width
=
'
100%
'
;
this
.
_webview
.
style
.
height
=
'
100%
'
;
return
;
this
.
_register
(
this
.
on
(
'
did-set-content
'
,
()
=>
{
if
(
this
.
element
)
{
this
.
element
.
style
.
flex
=
''
;
this
.
element
.
style
.
width
=
'
100%
'
;
this
.
element
.
style
.
height
=
'
100%
'
;
}
}));
case
'
did-scroll
'
:
if
(
event
.
args
&&
typeof
event
.
args
[
0
]
===
'
number
'
)
{
this
.
_onDidScroll
.
fire
({
scrollYPercentage
:
event
.
args
[
0
]
});
}
return
;
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
didScroll
,
(
scrollYPercentage
:
number
)
=>
{
this
.
_onDidScroll
.
fire
({
scrollYPercentage
:
scrollYPercentage
});
}));
case
'
do-reload
'
:
this
.
reload
();
return
;
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
doReload
,
()
=>
{
this
.
reload
();
}))
;
case
'
do-update-state
'
:
const
state
=
event
.
args
[
0
];
this
.
state
=
state
;
this
.
_onDidUpdateState
.
fire
(
state
);
return
;
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
doUpdateState
,
(
state
:
any
)
=>
{
this
.
state
=
state
;
this
.
_onDidUpdateState
.
fire
(
state
);
}));
case
'
did-focus
'
:
this
.
handleFocusChange
(
true
);
return
;
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
didFocus
,
()
=>
{
this
.
handleFocusChange
(
true
);
}))
;
case
'
did-blur
'
:
this
.
handleFocusChange
(
false
);
return
;
this
.
_register
(
this
.
on
(
WebviewMessageChannels
.
didBlur
,
()
=>
{
this
.
handleFocusChange
(
false
);
}))
;
case
'
no-csp-found
'
:
this
.
handleNoCspFound
();
return
;
}
this
.
_register
(
this
.
on
(
'
no-csp-found
'
,
()
=>
{
this
.
handleNoCspFound
();
}));
this
.
_register
(
addDisposableListener
(
this
.
_webview
,
'
devtools-opened
'
,
()
=>
{
this
.
_register
(
addDisposableListener
(
this
.
element
!
,
'
devtools-opened
'
,
()
=>
{
this
.
_send
(
'
devtools-opened
'
);
}));
if
(
options
.
enableFindWidget
)
{
this
.
_webviewFindWidget
=
this
.
_register
(
instantiationService
.
createInstance
(
WebviewFindWidget
,
this
));
this
.
_register
(
addDisposableListener
(
this
.
_webview
,
'
found-in-page
'
,
e
=>
{
this
.
_register
(
addDisposableListener
(
this
.
element
!
,
'
found-in-page
'
,
e
=>
{
this
.
_hasFindResult
.
fire
(
e
.
result
.
matches
>
0
);
}));
}
...
...
@@ -407,24 +371,32 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview,
this
.
_register
(
webviewThemeDataProvider
.
onThemeDataChanged
(
this
.
style
,
this
));
}
protected
createElement
(
options
:
WebviewOptions
)
{
const
element
=
document
.
createElement
(
'
webview
'
);
element
.
setAttribute
(
'
partition
'
,
`webview
${
Date
.
now
()}
`
);
element
.
setAttribute
(
'
webpreferences
'
,
'
contextIsolation=yes
'
);
element
.
className
=
`webview
${
options
.
customClasses
}
`
;
element
.
style
.
flex
=
'
0 1
'
;
element
.
style
.
width
=
'
0
'
;
element
.
style
.
height
=
'
0
'
;
element
.
style
.
outline
=
'
0
'
;
element
.
preload
=
require
.
toUrl
(
'
./pre/electron-index.js
'
);
element
.
src
=
'
data:text/html;charset=utf-8,%3C%21DOCTYPE%20html%3E%0D%0A%3Chtml%20lang%3D%22en%22%20style%3D%22width%3A%20100%25%3B%20height%3A%20100%25%22%3E%0D%0A%3Chead%3E%0D%0A%09%3Ctitle%3EVirtual%20Document%3C%2Ftitle%3E%0D%0A%3C%2Fhead%3E%0D%0A%3Cbody%20style%3D%22margin%3A%200%3B%20overflow%3A%20hidden%3B%20width%3A%20100%25%3B%20height%3A%20100%25%22%3E%0D%0A%3C%2Fbody%3E%0D%0A%3C%2Fhtml%3E
'
;
return
element
;
}
public
mountTo
(
parent
:
HTMLElement
)
{
if
(
!
this
.
_webview
)
{
if
(
!
this
.
element
)
{
return
;
}
if
(
this
.
_webviewFindWidget
)
{
parent
.
appendChild
(
this
.
_webviewFindWidget
.
getDomNode
()
!
);
}
parent
.
appendChild
(
this
.
_webview
);
}
dispose
():
void
{
if
(
this
.
_webview
)
{
this
.
_webview
.
remove
();
this
.
_webview
=
undefined
;
}
super
.
dispose
();
parent
.
appendChild
(
this
.
element
);
}
private
readonly
_onDidClickLink
=
this
.
_register
(
new
Emitter
<
URI
>
());
...
...
@@ -445,8 +417,8 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview,
private
_send
(
channel
:
string
,
data
?:
any
):
void
{
this
.
_ready
.
then
(()
=>
{
if
(
this
.
_webview
)
{
this
.
_webview
.
send
(
channel
,
data
);
if
(
this
.
element
)
{
this
.
element
.
send
(
channel
,
data
);
}
})
.
catch
(
err
=>
console
.
error
(
err
));
...
...
@@ -495,11 +467,11 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview,
}
public
focus
():
void
{
if
(
!
this
.
_webview
)
{
if
(
!
this
.
element
)
{
return
;
}
try
{
this
.
_webview
.
focus
();
this
.
element
.
focus
();
}
catch
{
// noop
}
...
...
@@ -559,7 +531,7 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview,
public
readonly
hasFindResult
:
Event
<
boolean
>
=
this
.
_hasFindResult
.
event
;
public
startFind
(
value
:
string
,
options
?:
FindInPageOptions
)
{
if
(
!
value
||
!
this
.
_webview
)
{
if
(
!
value
||
!
this
.
element
)
{
return
;
}
...
...
@@ -575,7 +547,7 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview,
};
this
.
_findStarted
=
true
;
this
.
_webview
.
findInPage
(
value
,
findOptions
);
this
.
element
.
findInPage
(
value
,
findOptions
);
}
/**
...
...
@@ -586,7 +558,7 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview,
* @param value The string to search for. Empty strings are ignored.
*/
public
find
(
value
:
string
,
previous
:
boolean
):
void
{
if
(
!
this
.
_webview
)
{
if
(
!
this
.
element
)
{
return
;
}
...
...
@@ -601,16 +573,16 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview,
return
;
}
this
.
_webview
.
findInPage
(
value
,
options
);
this
.
element
.
findInPage
(
value
,
options
);
}
public
stopFind
(
keepSelection
?:
boolean
):
void
{
this
.
_hasFindResult
.
fire
(
false
);
if
(
!
this
.
_webview
)
{
if
(
!
this
.
element
)
{
return
;
}
this
.
_findStarted
=
false
;
this
.
_webview
.
stopFindInPage
(
keepSelection
?
'
keepSelection
'
:
'
clearSelection
'
);
this
.
element
.
stopFindInPage
(
keepSelection
?
'
keepSelection
'
:
'
clearSelection
'
);
}
public
showFind
()
{
...
...
@@ -636,38 +608,52 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview,
}
public
selectAll
()
{
if
(
this
.
_webview
)
{
this
.
_webview
.
selectAll
();
if
(
this
.
element
)
{
this
.
element
.
selectAll
();
}
}
public
copy
()
{
if
(
this
.
_webview
)
{
this
.
_webview
.
copy
();
if
(
this
.
element
)
{
this
.
element
.
copy
();
}
}
public
paste
()
{
if
(
this
.
_webview
)
{
this
.
_webview
.
paste
();
if
(
this
.
element
)
{
this
.
element
.
paste
();
}
}
public
cut
()
{
if
(
this
.
_webview
)
{
this
.
_webview
.
cut
();
if
(
this
.
element
)
{
this
.
element
.
cut
();
}
}
public
undo
()
{
if
(
this
.
_webview
)
{
this
.
_webview
.
undo
();
if
(
this
.
element
)
{
this
.
element
.
undo
();
}
}
public
redo
()
{
if
(
this
.
_webview
)
{
this
.
_webview
.
redo
();
if
(
this
.
element
)
{
this
.
element
.
redo
();
}
}
protected
on
<
T
=
unknown
>
(
channel
:
WebviewMessageChannels
|
string
,
handler
:
(
data
:
T
)
=>
void
):
IDisposable
{
if
(
!
this
.
element
)
{
return
Disposable
.
None
;
}
return
addDisposableListener
(
this
.
element
,
'
ipc-message
'
,
(
event
)
=>
{
if
(
!
this
.
element
)
{
return
;
}
if
(
event
.
channel
===
channel
&&
event
.
args
&&
event
.
args
.
length
)
{
handler
(
event
.
args
[
0
]);
}
});
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录