add files
9
.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
# clion
|
||||
.idea/
|
||||
cmake-build-debug/
|
||||
cmake-build-release/
|
||||
|
||||
# vs
|
||||
.vs/
|
||||
.vscode/
|
||||
|
||||
56
CMakeLists.txt
Normal file
@ -0,0 +1,56 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(PROJECT_NAME WebView2)
|
||||
project(${PROJECT_NAME})
|
||||
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(DLL_SOURCES
|
||||
packages/cpprestsdk.v141.2.10.12.1/build/native/x64/bin/cpprest141_2_10d.dll
|
||||
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x64/WebView2Loader.dll
|
||||
)
|
||||
file(GLOB LIB_SOURCES
|
||||
packages/cpprestsdk.v141.2.10.12.1/build/native/x64/lib/cpprest141_2_10d.lib
|
||||
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x64/WebView2Loader.dll.lib
|
||||
)
|
||||
else ()
|
||||
set(DLL_SOURCES
|
||||
packages/cpprestsdk.v141.2.10.12.1/build/native/x64/bin/cpprest141_2_10.dll
|
||||
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x64/WebView2Loader.dll
|
||||
)
|
||||
file(GLOB LIB_SOURCES
|
||||
packages/cpprestsdk.v141.2.10.12.1/build/native/x64/lib/cpprest141_2_10.lib
|
||||
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x64/WebView2Loader.dll.lib
|
||||
)
|
||||
endif ()
|
||||
|
||||
file(COPY ${DLL_SOURCES} DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||
|
||||
include_directories(packages/cpprestsdk.v141.2.10.12.1/build/native/include)
|
||||
include_directories(packages/Microsoft.Web.WebView2.1.0.961.33/build/native/include)
|
||||
include_directories(packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include)
|
||||
|
||||
file(GLOB ASSETS_SOURCES assets/*)
|
||||
|
||||
file(COPY ${ASSETS_SOURCES} DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||
|
||||
file(GLOB_RECURSE SOURCES src/**)
|
||||
|
||||
add_definitions(-DUNICODE)
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
WIN32
|
||||
${SOURCES}
|
||||
)
|
||||
|
||||
target_link_options(WebView2 PRIVATE
|
||||
"/ENTRY:wWinMainCRTStartup"
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
${LIB_SOURCES}
|
||||
)
|
||||
27
LICENSE
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * The name of Google Inc, Microsoft Corporation, or the names of its
|
||||
// contributors may not be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
29
assets/wvbrowser_ui/commands.js
Normal file
@ -0,0 +1,29 @@
|
||||
const commands = {
|
||||
MG_NAVIGATE: 1,
|
||||
MG_UPDATE_URI: 2,
|
||||
MG_GO_FORWARD: 3,
|
||||
MG_GO_BACK: 4,
|
||||
MG_NAV_STARTING: 5,
|
||||
MG_NAV_COMPLETED: 6,
|
||||
MG_RELOAD: 7,
|
||||
MG_CANCEL: 8,
|
||||
MG_CREATE_TAB: 10,
|
||||
MG_UPDATE_TAB: 11,
|
||||
MG_SWITCH_TAB: 12,
|
||||
MG_CLOSE_TAB: 13,
|
||||
MG_CLOSE_WINDOW: 14,
|
||||
MG_SHOW_OPTIONS: 15,
|
||||
MG_HIDE_OPTIONS: 16,
|
||||
MG_OPTIONS_LOST_FOCUS: 17,
|
||||
MG_OPTION_SELECTED: 18,
|
||||
MG_SECURITY_UPDATE: 19,
|
||||
MG_UPDATE_FAVICON: 20,
|
||||
MG_GET_SETTINGS: 21,
|
||||
MG_GET_FAVORITES: 22,
|
||||
MG_REMOVE_FAVORITE: 23,
|
||||
MG_CLEAR_CACHE: 24,
|
||||
MG_CLEAR_COOKIES: 25,
|
||||
MG_GET_HISTORY: 26,
|
||||
MG_REMOVE_HISTORY_ITEM: 27,
|
||||
MG_CLEAR_HISTORY: 28
|
||||
};
|
||||
16
assets/wvbrowser_ui/content_ui/favorites.html
Normal file
@ -0,0 +1,16 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Favorites</title>
|
||||
<link rel="shortcut icon" href="img/favorites.png">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<link rel="stylesheet" type="text/css" href="items.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="main-title">Favorites</h1>
|
||||
<div id="entries-container">
|
||||
You don't have any favorites.
|
||||
</div>
|
||||
<script src="../commands.js"></script>
|
||||
<script src="favorites.js"></script>
|
||||
<body>
|
||||
</html>
|
||||
95
assets/wvbrowser_ui/content_ui/favorites.js
Normal file
@ -0,0 +1,95 @@
|
||||
const messageHandler = event => {
|
||||
var message = event.data.message;
|
||||
var args = event.data.args;
|
||||
|
||||
switch (message) {
|
||||
case commands.MG_GET_FAVORITES:
|
||||
loadFavorites(args.favorites);
|
||||
break;
|
||||
default:
|
||||
console.log(`Unexpected message: ${JSON.stringify(event.data)}`);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
function requestFavorites() {
|
||||
let message = {
|
||||
message: commands.MG_GET_FAVORITES,
|
||||
args: {}
|
||||
};
|
||||
|
||||
window.chrome.webview.postMessage(message);
|
||||
}
|
||||
|
||||
function removeFavorite(uri) {
|
||||
let message = {
|
||||
message: commands.MG_REMOVE_FAVORITE,
|
||||
args: {
|
||||
uri: uri
|
||||
}
|
||||
};
|
||||
|
||||
window.chrome.webview.postMessage(message);
|
||||
}
|
||||
|
||||
function loadFavorites(payload) {
|
||||
let fragment = document.createDocumentFragment();
|
||||
|
||||
if (payload.length > 0) {
|
||||
let container = document.getElementById('entries-container');
|
||||
container.textContent = '';
|
||||
}
|
||||
|
||||
payload.map(favorite => {
|
||||
let favoriteContainer = document.createElement('div');
|
||||
favoriteContainer.className = 'item-container';
|
||||
let favoriteElement = document.createElement('div');
|
||||
favoriteElement.className = 'item';
|
||||
|
||||
let faviconElement = document.createElement('div');
|
||||
faviconElement.className = 'favicon';
|
||||
let faviconImage = document.createElement('img');
|
||||
faviconImage.src = favorite.favicon;
|
||||
faviconElement.appendChild(faviconImage);
|
||||
|
||||
let labelElement = document.createElement('div');
|
||||
labelElement.className = 'label-title';
|
||||
let linkElement = document.createElement('a');
|
||||
linkElement.textContent = favorite.title;
|
||||
linkElement.href = favorite.uri;
|
||||
linkElement.title = favorite.title;
|
||||
labelElement.appendChild(linkElement);
|
||||
|
||||
let uriElement = document.createElement('div');
|
||||
uriElement.className = 'label-uri';
|
||||
let textElement = document.createElement('p');
|
||||
textElement.textContent = favorite.uriToShow || favorite.uri;
|
||||
textElement.title = favorite.uriToShow || favorite.uri;
|
||||
uriElement.appendChild(textElement);
|
||||
|
||||
let buttonElement = document.createElement('div');
|
||||
buttonElement.className = 'btn-close';
|
||||
buttonElement.addEventListener('click', function(e) {
|
||||
favoriteContainer.parentNode.removeChild(favoriteContainer);
|
||||
removeFavorite(favorite.uri);
|
||||
});
|
||||
|
||||
favoriteElement.appendChild(faviconElement);
|
||||
favoriteElement.appendChild(labelElement);
|
||||
favoriteElement.appendChild(uriElement);
|
||||
favoriteElement.appendChild(buttonElement);
|
||||
|
||||
favoriteContainer.appendChild(favoriteElement);
|
||||
fragment.appendChild(favoriteContainer);
|
||||
});
|
||||
|
||||
let container = document.getElementById('entries-container');
|
||||
container.appendChild(fragment);
|
||||
}
|
||||
|
||||
function init() {
|
||||
window.chrome.webview.addEventListener('message', messageHandler);
|
||||
requestFavorites();
|
||||
}
|
||||
|
||||
init();
|
||||
81
assets/wvbrowser_ui/content_ui/history.css
Normal file
@ -0,0 +1,81 @@
|
||||
.header-date {
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: rgb(16, 16, 16);
|
||||
line-height: 20px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 4px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#btn-clear {
|
||||
font-size: 14px;
|
||||
color: rgb(0, 97, 171);
|
||||
cursor: pointer;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
#btn-clear.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
#overlay.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#prompt-box {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
position: fixed;
|
||||
left: calc(50% - 130px);
|
||||
top: calc(50% - 70px);
|
||||
width: 260px;
|
||||
height: 140px;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
background-color: white;
|
||||
|
||||
box-shadow: rgba(0, 0, 0, 0.13) 0px 1.6px 20px, rgba(0, 0, 0, 0.11) 0px 0.3px 10px;
|
||||
}
|
||||
|
||||
#prompt-options {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.prompt-btn {
|
||||
flex: 1;
|
||||
flex-grow: 0;
|
||||
align-self: flex-end;
|
||||
cursor: pointer;
|
||||
font-family: 'system-ui', sans-serif;
|
||||
display: inline-block;
|
||||
padding: 2px 7px;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
border-radius: 3px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
#prompt-true {
|
||||
background-color: rgb(0, 112, 198);
|
||||
color: white;
|
||||
}
|
||||
|
||||
#prompt-false {
|
||||
background-color: rgb(210, 210, 210);
|
||||
margin-right: 5px;
|
||||
}
|
||||
30
assets/wvbrowser_ui/content_ui/history.html
Normal file
@ -0,0 +1,30 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>History</title>
|
||||
<link rel="shortcut icon" href="img/history.png">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<link rel="stylesheet" type="text/css" href="items.css">
|
||||
<link rel="stylesheet" type="text/css" href="history.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="overlay" class="hidden">
|
||||
<div id="prompt-box">
|
||||
<span class="prompt-text">Clear history?</span>
|
||||
<div id="prompt-options">
|
||||
<div class="prompt-btn" id="prompt-false">Cancel</div>
|
||||
<div class="prompt-btn" id="prompt-true">Clear</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h1 class="main-title">History</h1>
|
||||
<div>
|
||||
<span id="btn-clear" class="hidden">Clear history</span>
|
||||
</div>
|
||||
<div id="entries-container">
|
||||
Loading...
|
||||
</div>
|
||||
|
||||
<script src="../commands.js"></script>
|
||||
<script src="history.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
273
assets/wvbrowser_ui/content_ui/history.js
Normal file
@ -0,0 +1,273 @@
|
||||
const DEFAULT_HISTORY_ITEM_COUNT = 20;
|
||||
const EMPTY_HISTORY_MESSAGE = `You haven't visited any sites yet.`;
|
||||
let requestedTop = 0;
|
||||
let lastRequestSize = 0;
|
||||
let itemHeight = 48;
|
||||
|
||||
const dateStringFormat = new Intl.DateTimeFormat('default', {
|
||||
weekday: 'long',
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric'
|
||||
});
|
||||
|
||||
const timeStringFormat = new Intl.DateTimeFormat('default', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
});
|
||||
|
||||
const messageHandler = event => {
|
||||
var message = event.data.message;
|
||||
var args = event.data.args;
|
||||
|
||||
switch (message) {
|
||||
case commands.MG_GET_HISTORY:
|
||||
let entriesContainer = document.getElementById('entries-container');
|
||||
if (args.from == 0 && args.items.length) {
|
||||
entriesContainer.textContent = '';
|
||||
|
||||
let clearButton = document.getElementById('btn-clear');
|
||||
clearButton.classList.remove('hidden');
|
||||
}
|
||||
|
||||
loadItems(args.items);
|
||||
if (args.items.length == lastRequestSize) {
|
||||
document.addEventListener('scroll', requestTrigger);
|
||||
} else if (entriesContainer.childElementCount == 0) {
|
||||
loadUIForEmptyHistory();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.log(`Unexpected message: ${JSON.stringify(event.data)}`);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const requestTrigger = function(event) {
|
||||
let triggerRange = 50;
|
||||
let element = document.body;
|
||||
|
||||
if (element.scrollTop + element.clientHeight >= element.scrollHeight - triggerRange) {
|
||||
getMoreHistoryItems();
|
||||
event.target.removeEventListener('scroll', requestTrigger);
|
||||
}
|
||||
};
|
||||
|
||||
function requestHistoryItems(from, count) {
|
||||
let message = {
|
||||
message: commands.MG_GET_HISTORY,
|
||||
args: {
|
||||
from: from,
|
||||
count: count || DEFAULT_HISTORY_ITEM_COUNT
|
||||
}
|
||||
};
|
||||
|
||||
window.chrome.webview.postMessage(message);
|
||||
}
|
||||
|
||||
function removeItem(id) {
|
||||
let message = {
|
||||
message: commands.MG_REMOVE_HISTORY_ITEM,
|
||||
args: {
|
||||
id: id
|
||||
}
|
||||
};
|
||||
|
||||
window.chrome.webview.postMessage(message);
|
||||
}
|
||||
|
||||
function createItemElement(item, id, date) {
|
||||
let itemContainer = document.createElement('div');
|
||||
itemContainer.id = id;
|
||||
itemContainer.className = 'item-container';
|
||||
|
||||
let itemElement = document.createElement('div');
|
||||
itemElement.className = 'item';
|
||||
|
||||
// Favicon
|
||||
let faviconElement = document.createElement('div');
|
||||
faviconElement.className = 'favicon';
|
||||
let faviconImage = document.createElement('img');
|
||||
faviconImage.src = item.favicon;
|
||||
faviconElement.append(faviconImage);
|
||||
itemElement.append(faviconElement);
|
||||
|
||||
// Title
|
||||
let titleLabel = document.createElement('div');
|
||||
titleLabel.className = 'label-title';
|
||||
let linkElement = document.createElement('a');
|
||||
linkElement.href = item.uri;
|
||||
linkElement.title = item.title;
|
||||
linkElement.textContent = item.title;
|
||||
titleLabel.append(linkElement);
|
||||
itemElement.append(titleLabel);
|
||||
|
||||
// URI
|
||||
let uriLabel = document.createElement('div');
|
||||
uriLabel.className = 'label-uri';
|
||||
let textElement = document.createElement('p');
|
||||
textElement.title = item.uri;
|
||||
textElement.textContent = item.uri;
|
||||
uriLabel.append(textElement);
|
||||
itemElement.append(uriLabel);
|
||||
|
||||
// Time
|
||||
let timeLabel = document.createElement('div');
|
||||
timeLabel.className = 'label-time';
|
||||
let timeText = document.createElement('p');
|
||||
timeText.textContent = timeStringFormat.format(date);
|
||||
timeLabel.append(timeText);
|
||||
itemElement.append(timeLabel);
|
||||
|
||||
// Close button
|
||||
let closeButton = document.createElement('div');
|
||||
closeButton.className = 'btn-close';
|
||||
closeButton.addEventListener('click', function(e) {
|
||||
if (itemContainer.parentNode.children.length <= 2) {
|
||||
itemContainer.parentNode.remove();
|
||||
} else {
|
||||
itemContainer.remove();
|
||||
}
|
||||
|
||||
let entriesContainer = document.getElementById('entries-container');
|
||||
if (entriesContainer.childElementCount == 0) {
|
||||
loadUIForEmptyHistory();
|
||||
}
|
||||
removeItem(parseInt(id.split('-')[1]));
|
||||
});
|
||||
itemElement.append(closeButton);
|
||||
itemContainer.append(itemElement);
|
||||
|
||||
return itemContainer;
|
||||
}
|
||||
|
||||
function createDateContainer(id, date) {
|
||||
let dateContainer = document.createElement('div');
|
||||
dateContainer.id = id;
|
||||
|
||||
let dateLabel = document.createElement('h3');
|
||||
dateLabel.className = 'header-date';
|
||||
dateLabel.textContent = dateStringFormat.format(date);
|
||||
dateContainer.append(dateLabel);
|
||||
|
||||
return dateContainer;
|
||||
}
|
||||
|
||||
function loadItems(items) {
|
||||
let dateContainer;
|
||||
let fragment;
|
||||
|
||||
items.map((entry) => {
|
||||
let id = entry.id;
|
||||
let item = entry.item;
|
||||
let itemContainerId = `item-${id}`;
|
||||
|
||||
// Skip the item if already loaded. This could happen if the user
|
||||
// visits an item for the current date again before requesting more
|
||||
// history items.
|
||||
let itemContainer = document.getElementById(itemContainerId);
|
||||
if (itemContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
let date = new Date(item.timestamp);
|
||||
let day = date.getDate();
|
||||
let month = date.getMonth();
|
||||
let year = date.getFullYear();
|
||||
let dateContainerId = `entries-${month}-${day}-${year}`;
|
||||
|
||||
// If entry belongs to a new date, append buffered items for previous
|
||||
// date.
|
||||
if (dateContainer && dateContainer.id != dateContainerId) {
|
||||
dateContainer.append(fragment);
|
||||
}
|
||||
|
||||
dateContainer = document.getElementById(dateContainerId);
|
||||
if (!dateContainer) {
|
||||
dateContainer = createDateContainer(dateContainerId, date);
|
||||
fragment = document.createDocumentFragment();
|
||||
|
||||
let entriesContainer = document.getElementById('entries-container');
|
||||
entriesContainer.append(dateContainer);
|
||||
} else if (!fragment) {
|
||||
fragment = document.createDocumentFragment();
|
||||
}
|
||||
|
||||
itemContainer = createItemElement(item, itemContainerId, date);
|
||||
fragment.append(itemContainer);
|
||||
});
|
||||
|
||||
// Append remaining items in buffer
|
||||
if (fragment) {
|
||||
dateContainer.append(fragment);
|
||||
}
|
||||
}
|
||||
|
||||
function getMoreHistoryItems(n) {
|
||||
n = n ? n : DEFAULT_HISTORY_ITEM_COUNT;
|
||||
|
||||
requestHistoryItems(requestedTop, n);
|
||||
requestedTop += n;
|
||||
lastRequestSize = n;
|
||||
document.removeEventListener('scroll', requestTrigger);
|
||||
}
|
||||
|
||||
function addUIListeners() {
|
||||
let confirmButton = document.getElementById('prompt-true');
|
||||
confirmButton.addEventListener('click', function(event) {
|
||||
clearHistory();
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
let cancelButton = document.getElementById('prompt-false');
|
||||
cancelButton.addEventListener('click', function(event) {
|
||||
toggleClearPrompt();
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
let promptBox = document.getElementById('prompt-box');
|
||||
promptBox.addEventListener('click', function(event) {
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
let promptOverlay = document.getElementById('overlay');
|
||||
promptOverlay.addEventListener('click', toggleClearPrompt);
|
||||
|
||||
let clearButton = document.getElementById('btn-clear');
|
||||
clearButton.addEventListener('click', toggleClearPrompt);
|
||||
}
|
||||
|
||||
function toggleClearPrompt() {
|
||||
let promptOverlay = document.getElementById('overlay');
|
||||
promptOverlay.classList.toggle('hidden');
|
||||
}
|
||||
|
||||
function loadUIForEmptyHistory() {
|
||||
let entriesContainer = document.getElementById('entries-container');
|
||||
entriesContainer.textContent = EMPTY_HISTORY_MESSAGE;
|
||||
|
||||
let clearButton = document.getElementById('btn-clear');
|
||||
clearButton.classList.add('hidden');
|
||||
}
|
||||
|
||||
function clearHistory() {
|
||||
toggleClearPrompt();
|
||||
loadUIForEmptyHistory();
|
||||
|
||||
let message = {
|
||||
message: commands.MG_CLEAR_HISTORY,
|
||||
args: {}
|
||||
};
|
||||
|
||||
window.chrome.webview.postMessage(message);
|
||||
}
|
||||
|
||||
function init() {
|
||||
window.chrome.webview.addEventListener('message', messageHandler);
|
||||
|
||||
let viewportItemsCapacity = Math.round(window.innerHeight / itemHeight);
|
||||
addUIListeners();
|
||||
getMoreHistoryItems(viewportItemsCapacity);
|
||||
}
|
||||
|
||||
init();
|
||||
BIN
assets/wvbrowser_ui/content_ui/img/close.png
Normal file
|
After Width: | Height: | Size: 715 B |
BIN
assets/wvbrowser_ui/content_ui/img/favorites.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
assets/wvbrowser_ui/content_ui/img/history.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
assets/wvbrowser_ui/content_ui/img/settings.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
92
assets/wvbrowser_ui/content_ui/items.css
Normal file
@ -0,0 +1,92 @@
|
||||
.item-container {
|
||||
box-sizing: border-box;
|
||||
padding: 4px 0;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
max-width: 820px;
|
||||
height: 40px;
|
||||
width: 100%;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
box-shadow: rgba(0, 0, 0, 0.13) 0px 1.6px 3.6px, rgba(0, 0, 0, 0.11) 0px 0.3px 0.9px;
|
||||
align-items: center;
|
||||
background: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
.item:hover {
|
||||
box-shadow: 0px 4.8px 10.8px rgba(0,0,0,0.13), 0px 0.9px 2.7px rgba(0,0,0,0.11);
|
||||
}
|
||||
|
||||
.favicon {
|
||||
display: flex;
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.favicon img {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.label-title, .label-uri {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
height: 40px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.label-title a {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
font-weight: 600;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
color: rgb(16, 16, 16);
|
||||
border-width: initial;
|
||||
border-style: none;
|
||||
border-color: initial;
|
||||
border-image: initial;
|
||||
overflow: hidden;
|
||||
background: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.label-title a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.label-uri, .label-time {
|
||||
margin: 0 6px;
|
||||
line-height: 16px;
|
||||
font-size: 12px;
|
||||
color: rgb(115, 115, 115);
|
||||
}
|
||||
|
||||
.label-uri p, .label-time p {
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.btn-close {
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
margin: 6px;
|
||||
border-radius: 2px;
|
||||
background-image: url('img/close.png');
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.btn-close:hover {
|
||||
background-color: rgb(243, 243, 243);
|
||||
}
|
||||
54
assets/wvbrowser_ui/content_ui/settings.css
Normal file
@ -0,0 +1,54 @@
|
||||
.settings-entry {
|
||||
display: block;
|
||||
height: 48px;
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 4px 0;
|
||||
font: inherit;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#entry-script, #entry-popups {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.entry {
|
||||
display: block;
|
||||
height: 100%;
|
||||
text-align: left;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.entry:hover {
|
||||
background-color: rgb(220, 220, 220);
|
||||
}
|
||||
|
||||
.entry:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.entry-name, .entry-value {
|
||||
display: inline-flex;
|
||||
height: 100%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.entry-name span, .entry-value span {
|
||||
flex: 1;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.entry-name {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.entry-value {
|
||||
float: right;
|
||||
vertical-align: middle;
|
||||
margin: 0 15px;
|
||||
font-size: 0.8em;
|
||||
color: gray;
|
||||
}
|
||||
56
assets/wvbrowser_ui/content_ui/settings.html
Normal file
@ -0,0 +1,56 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Settings</title>
|
||||
<link rel="shortcut icon" href="img/settings.png">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<link rel="stylesheet" type="text/css" href="settings.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="main-title">Settings</h1>
|
||||
<div class="page-content">
|
||||
<button class="settings-entry" id="entry-cache">
|
||||
<div class="entry">
|
||||
<div class="entry-name">
|
||||
<span>Clear cache</span>
|
||||
</div>
|
||||
<div class="entry-value">
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
<button class="settings-entry" id="entry-cookies">
|
||||
<div class="entry">
|
||||
<div class="entry-name">
|
||||
<span>Clear cookies</span>
|
||||
</div>
|
||||
<div class="entry-value">
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
<button class="settings-entry" id="entry-script">
|
||||
<div class="entry">
|
||||
<div class="entry-name">
|
||||
<span>Toggle JavaScript</span>
|
||||
</div>
|
||||
<div class="entry-value">
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
<button class="settings-entry" id="entry-popups">
|
||||
<div class="entry">
|
||||
<div class="entry-name">
|
||||
<span>Block pop-ups</span>
|
||||
</div>
|
||||
<div class="entry-value">
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<script src="../commands.js"></script>
|
||||
<script src="settings.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
107
assets/wvbrowser_ui/content_ui/settings.js
Normal file
@ -0,0 +1,107 @@
|
||||
const messageHandler = event => {
|
||||
var message = event.data.message;
|
||||
var args = event.data.args;
|
||||
|
||||
switch (message) {
|
||||
case commands.MG_GET_SETTINGS:
|
||||
loadSettings(args.settings);
|
||||
break;
|
||||
case commands.MG_CLEAR_CACHE:
|
||||
if (args.content && args.controls) {
|
||||
updateLabelForEntry('entry-cache', 'Cleared');
|
||||
} else {
|
||||
updateLabelForEntry('entry-cache', 'Try again');
|
||||
}
|
||||
break;
|
||||
case commands.MG_CLEAR_COOKIES:
|
||||
if (args.content && args.controls) {
|
||||
updateLabelForEntry('entry-cookies', 'Cleared');
|
||||
} else {
|
||||
updateLabelForEntry('entry-cookies', 'Try again');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.log(`Unexpected message: ${JSON.stringify(event.data)}`);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
function addEntriesListeners() {
|
||||
let cacheEntry = document.getElementById('entry-cache');
|
||||
cacheEntry.addEventListener('click', function(e) {
|
||||
let message = {
|
||||
message: commands.MG_CLEAR_CACHE,
|
||||
args: {}
|
||||
};
|
||||
|
||||
window.chrome.webview.postMessage(message);
|
||||
});
|
||||
|
||||
let cookiesEntry = document.getElementById('entry-cookies');
|
||||
cookiesEntry.addEventListener('click', function(e) {
|
||||
let message = {
|
||||
message: commands.MG_CLEAR_COOKIES,
|
||||
args: {}
|
||||
};
|
||||
|
||||
window.chrome.webview.postMessage(message);
|
||||
});
|
||||
|
||||
let scriptEntry = document.getElementById('entry-script');
|
||||
scriptEntry.addEventListener('click', function(e) {
|
||||
// Toggle script support
|
||||
});
|
||||
|
||||
let popupsEntry = document.getElementById('entry-popups');
|
||||
popupsEntry.addEventListener('click', function(e) {
|
||||
// Toggle popups
|
||||
});
|
||||
}
|
||||
|
||||
function requestBrowserSettings() {
|
||||
let message = {
|
||||
message: commands.MG_GET_SETTINGS,
|
||||
args: {}
|
||||
};
|
||||
|
||||
window.chrome.webview.postMessage(message);
|
||||
}
|
||||
|
||||
function loadSettings(settings) {
|
||||
if (settings.scriptsEnabled) {
|
||||
updateLabelForEntry('entry-script', 'Enabled');
|
||||
} else {
|
||||
updateLabelForEntry('entry-script', 'Disabled');
|
||||
}
|
||||
|
||||
if (settings.blockPopups) {
|
||||
updateLabelForEntry('entry-popups', 'Blocked');
|
||||
} else {
|
||||
updateLabelForEntry('entry-popups', 'Allowed');
|
||||
}
|
||||
}
|
||||
|
||||
function updateLabelForEntry(elementId, label) {
|
||||
let entryElement = document.getElementById(elementId);
|
||||
if (!entryElement) {
|
||||
console.log(`Element with id ${elementId} does not exist`);
|
||||
return;
|
||||
}
|
||||
|
||||
let labelSpan = entryElement.querySelector(`.entry-value span`);
|
||||
|
||||
if (!labelSpan) {
|
||||
console.log(`${elementId} does not have a label`);
|
||||
return;
|
||||
}
|
||||
|
||||
labelSpan.textContent = label;
|
||||
}
|
||||
|
||||
function init() {
|
||||
window.chrome.webview.addEventListener('message', messageHandler);
|
||||
requestBrowserSettings();
|
||||
addEntriesListeners();
|
||||
}
|
||||
|
||||
init();
|
||||
25
assets/wvbrowser_ui/content_ui/styles.css
Normal file
@ -0,0 +1,25 @@
|
||||
html, body {
|
||||
margin: 0;
|
||||
border: none;
|
||||
padding: 0;
|
||||
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
background-color: rgb(240, 240, 242);
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 32px 50px;
|
||||
font-family: 'system-ui', sans-serif;
|
||||
}
|
||||
|
||||
.main-title {
|
||||
display: block;
|
||||
margin-bottom: 18px;
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: rgb(16, 16, 16);
|
||||
}
|
||||
135
assets/wvbrowser_ui/controls_ui/address-bar.css
Normal file
@ -0,0 +1,135 @@
|
||||
#address-bar-container {
|
||||
display: flex;
|
||||
height: calc(100% - 10px);
|
||||
width: 80%;
|
||||
max-width: calc(100% - 160px);
|
||||
|
||||
background-color: white;
|
||||
border: 1px solid gray;
|
||||
border-radius: 5px;
|
||||
|
||||
position: relative;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
#address-bar-container:focus-within {
|
||||
outline: none;
|
||||
box-shadow: 0 0 3px dodgerblue;
|
||||
}
|
||||
|
||||
#address-bar-container:focus-within #btn-clear {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#security-label {
|
||||
display: inline-flex;
|
||||
height: 100%;
|
||||
margin-left: 2px;
|
||||
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#security-label span {
|
||||
font-family: Arial;
|
||||
font-size: 0.9em;
|
||||
color: gray;
|
||||
vertical-align: middle;
|
||||
flex: 1;
|
||||
align-self: center;
|
||||
text-align: left;
|
||||
padding-left: 5px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.icn {
|
||||
display: inline-block;
|
||||
margin: 2px 0;
|
||||
border-radius: 5px;
|
||||
top: 0;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
#icn-lock {
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
#security-label.label-unknown .icn {
|
||||
background-image: url('img/unknown.png');
|
||||
}
|
||||
|
||||
#security-label.label-insecure .icn {
|
||||
background-image: url('img/insecure.png');
|
||||
}
|
||||
|
||||
#security-label.label-insecure span {
|
||||
color: rgb(192, 0, 0);
|
||||
}
|
||||
|
||||
#security-label.label-neutral .icn {
|
||||
background-image: url('img/neutral.png');
|
||||
}
|
||||
|
||||
#security-label.label-secure .icn {
|
||||
background-image: url('img/secure.png');
|
||||
}
|
||||
|
||||
#security-label.label-secure span, #security-label.label-neutral span {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#icn-favicon {
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
#img-favicon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
#address-form {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#address-field {
|
||||
flex: 1;
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
margin: 0;
|
||||
|
||||
line-height: 30px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#address-field:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#btn-fav {
|
||||
margin: 2px 5px;
|
||||
background-size: 100%;
|
||||
background-image: url('img/favorite.png');
|
||||
}
|
||||
|
||||
#btn-fav:hover, #btn-clear:hover {
|
||||
background-color: rgb(230, 230, 230);
|
||||
}
|
||||
|
||||
#btn-fav.favorited {
|
||||
background-image: url('img/favorited.png');
|
||||
}
|
||||
|
||||
#btn-clear {
|
||||
display: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: none;
|
||||
align-self: center;
|
||||
background-color: transparent;
|
||||
background-image: url(img/cancel.png);
|
||||
background-size: 100%;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
}
|
||||
66
assets/wvbrowser_ui/controls_ui/controls.css
Normal file
@ -0,0 +1,66 @@
|
||||
#controls-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: row;
|
||||
height: 40px;
|
||||
background-color: rgb(230, 230, 230);
|
||||
}
|
||||
|
||||
.btn, .btn-disabled, .btn-cancel, .btn-active {
|
||||
display: inline-block;
|
||||
border: none;
|
||||
margin: 5px 0;
|
||||
border-radius: 5px;
|
||||
outline: none;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
#btn-forward {
|
||||
background-image: url('img/goForward.png');
|
||||
}
|
||||
|
||||
.btn-disabled#btn-forward {
|
||||
background-image: url('img/goForward_disabled.png');
|
||||
}
|
||||
|
||||
#btn-back {
|
||||
background-image: url('img/goBack.png');
|
||||
}
|
||||
|
||||
.btn-disabled#btn-back {
|
||||
background-image: url('img/goBack_disabled.png');
|
||||
}
|
||||
|
||||
#btn-reload {
|
||||
background-image: url('img/reload.png');
|
||||
}
|
||||
|
||||
.btn-cancel#btn-reload {
|
||||
background-image: url('img/cancel.png');
|
||||
}
|
||||
|
||||
#btn-options {
|
||||
background-image: url('img/options.png');
|
||||
}
|
||||
|
||||
.controls-group {
|
||||
display: inline-block;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
#nav-controls-container {
|
||||
align-self: flex-start;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
#manage-controls-container {
|
||||
align-self: flex-end;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.btn:hover, .btn-cancel:hover, .btn-active {
|
||||
background-color: rgb(200, 200, 200);
|
||||
}
|
||||
3
assets/wvbrowser_ui/controls_ui/default.css
Normal file
@ -0,0 +1,3 @@
|
||||
html, body {
|
||||
height: 70px;
|
||||
}
|
||||
17
assets/wvbrowser_ui/controls_ui/default.html
Normal file
@ -0,0 +1,17 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<link rel="stylesheet" type="text/css" href="default.css">
|
||||
<link rel="stylesheet" type="text/css" href="controls.css">
|
||||
<link rel="stylesheet" type="text/css" href="address-bar.css">
|
||||
<link rel="stylesheet" type="text/css" href="strip.css">
|
||||
</head>
|
||||
<body>
|
||||
<script src="../commands.js"></script>
|
||||
<script src="tabs.js"></script>
|
||||
<script src="storage.js"></script>
|
||||
<script src="favorites.js"></script>
|
||||
<script src="history.js"></script>
|
||||
<script src="default.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
736
assets/wvbrowser_ui/controls_ui/default.js
Normal file
@ -0,0 +1,736 @@
|
||||
const WORD_REGEX = /^[^//][^.]*$/;
|
||||
const VALID_URI_REGEX = /^[-:.&#+()[\]$'*;@~!,?%=\/\w]+$/; // Will check that only RFC3986 allowed characters are included
|
||||
const SCHEMED_URI_REGEX = /^\w+:.+$/;
|
||||
|
||||
let settings = {
|
||||
scriptsEnabled: true,
|
||||
blockPopups: true
|
||||
};
|
||||
|
||||
const messageHandler = event => {
|
||||
var message = event.data.message;
|
||||
var args = event.data.args;
|
||||
|
||||
switch (message) {
|
||||
case commands.MG_UPDATE_URI:
|
||||
if (isValidTabId(args.tabId)) {
|
||||
const tab = tabs.get(args.tabId);
|
||||
let previousURI = tab.uri;
|
||||
|
||||
// Update the tab state
|
||||
tab.uri = args.uri;
|
||||
tab.uriToShow = args.uriToShow;
|
||||
tab.canGoBack = args.canGoBack;
|
||||
tab.canGoForward = args.canGoForward;
|
||||
|
||||
// If the tab is active, update the controls UI
|
||||
if (args.tabId == activeTabId) {
|
||||
updateNavigationUI(message);
|
||||
}
|
||||
|
||||
isFavorite(tab.uri, (isFavorite) => {
|
||||
tab.isFavorite = isFavorite;
|
||||
updateFavoriteIcon();
|
||||
});
|
||||
|
||||
// Don't add history entry if URI has not changed
|
||||
if (tab.uri == previousURI) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Filter URIs that should not appear in history
|
||||
if (!tab.uri || tab.uri == 'about:blank') {
|
||||
tab.historyItemId = INVALID_HISTORY_ID;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tab.uriToShow && tab.uriToShow.substring(0, 10) == 'browser://') {
|
||||
tab.historyItemId = INVALID_HISTORY_ID;
|
||||
break;
|
||||
}
|
||||
|
||||
addHistoryItem(historyItemFromTab(args.tabId), (id) => {
|
||||
tab.historyItemId = id;
|
||||
});
|
||||
}
|
||||
break;
|
||||
case commands.MG_NAV_STARTING:
|
||||
if (isValidTabId(args.tabId)) {
|
||||
// Update the tab state
|
||||
tabs.get(args.tabId).isLoading = true;
|
||||
|
||||
// If the tab is active, update the controls UI
|
||||
if (args.tabId == activeTabId) {
|
||||
updateNavigationUI(message);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case commands.MG_NAV_COMPLETED:
|
||||
if (isValidTabId(args.tabId)) {
|
||||
// Update tab state
|
||||
tabs.get(args.tabId).isLoading = false;
|
||||
|
||||
// If the tab is active, update the controls UI
|
||||
if (args.tabId == activeTabId) {
|
||||
updateNavigationUI(message);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case commands.MG_UPDATE_TAB:
|
||||
if (isValidTabId(args.tabId)) {
|
||||
const tab = tabs.get(args.tabId);
|
||||
const tabElement = document.getElementById(`tab-${args.tabId}`);
|
||||
|
||||
if (!tabElement) {
|
||||
refreshTabs();
|
||||
return;
|
||||
}
|
||||
|
||||
// Update tab label
|
||||
// Use given title or fall back to a generic tab title
|
||||
tab.title = args.title || 'Tab';
|
||||
const tabLabel = tabElement.firstChild;
|
||||
const tabLabelSpan = tabLabel.firstChild;
|
||||
tabLabelSpan.textContent = tab.title;
|
||||
|
||||
// Update title in history item
|
||||
// Browser pages will keep an invalid history ID
|
||||
if (tab.historyItemId != INVALID_HISTORY_ID) {
|
||||
updateHistoryItem(tab.historyItemId, historyItemFromTab(args.tabId));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case commands.MG_OPTIONS_LOST_FOCUS:
|
||||
let optionsButton = document.getElementById('btn-options');
|
||||
if (optionsButton) {
|
||||
if (optionsButton.className = 'btn-active') {
|
||||
toggleOptionsDropdown();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case commands.MG_SECURITY_UPDATE:
|
||||
if (isValidTabId(args.tabId)) {
|
||||
const tab = tabs.get(args.tabId);
|
||||
tab.securityState = args.state;
|
||||
|
||||
if (args.tabId == activeTabId) {
|
||||
updateNavigationUI(message);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case commands.MG_UPDATE_FAVICON:
|
||||
if (isValidTabId(args.tabId)) {
|
||||
updateFaviconURI(args.tabId, args.uri);
|
||||
}
|
||||
break;
|
||||
case commands.MG_CLOSE_WINDOW:
|
||||
closeWindow();
|
||||
break;
|
||||
case commands.MG_CLOSE_TAB:
|
||||
if (isValidTabId(args.tabId)) {
|
||||
closeTab(args.tabId);
|
||||
}
|
||||
break;
|
||||
case commands.MG_GET_FAVORITES:
|
||||
if (isValidTabId(args.tabId)) {
|
||||
getFavoritesAsJson((payload) => {
|
||||
args.favorites = payload;
|
||||
window.chrome.webview.postMessage(event.data);
|
||||
});
|
||||
}
|
||||
break;
|
||||
case commands.MG_REMOVE_FAVORITE:
|
||||
removeFavorite(args.uri);
|
||||
break;
|
||||
case commands.MG_GET_SETTINGS:
|
||||
if (isValidTabId(args.tabId)) {
|
||||
args.settings = settings;
|
||||
window.chrome.webview.postMessage(event.data);
|
||||
}
|
||||
break;
|
||||
case commands.MG_GET_HISTORY:
|
||||
if (isValidTabId(args.tabId)) {
|
||||
getHistoryItems(args.from, args.count, (payload) => {
|
||||
args.items = payload;
|
||||
window.chrome.webview.postMessage(event.data);
|
||||
});
|
||||
}
|
||||
break;
|
||||
case commands.MG_REMOVE_HISTORY_ITEM:
|
||||
removeHistoryItem(args.id);
|
||||
break;
|
||||
case commands.MG_CLEAR_HISTORY:
|
||||
clearHistory();
|
||||
break;
|
||||
default:
|
||||
console.log(`Received unexpected message: ${JSON.stringify(event.data)}`);
|
||||
}
|
||||
};
|
||||
|
||||
function processAddressBarInput() {
|
||||
var text = document.querySelector('#address-field').value;
|
||||
tryNavigate(text);
|
||||
}
|
||||
|
||||
function tryNavigate(text) {
|
||||
try {
|
||||
var uriParser = new URL(text);
|
||||
|
||||
// URL creation succeeded, verify protocol is allowed
|
||||
switch (uriParser.protocol) {
|
||||
case 'http:':
|
||||
case 'https:':
|
||||
case 'file:':
|
||||
case 'ftp:':
|
||||
// Allowed protocol, navigate
|
||||
navigateActiveTab(uriParser.href, false);
|
||||
break;
|
||||
default:
|
||||
// Protocol not allowed, search Bing
|
||||
navigateActiveTab(getSearchURI(text), true);
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
// URL creation failed, check for invalid characters
|
||||
if (containsIlegalCharacters(text) || isSingleWord(text)) {
|
||||
// Search Bing
|
||||
navigateActiveTab(getSearchURI(text), true);
|
||||
} else {
|
||||
// Try with HTTP
|
||||
if (!hasScheme(text)) {
|
||||
tryNavigate(`http:${text}`);
|
||||
} else {
|
||||
navigateActiveTab(getSearchURI(text), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function navigateActiveTab(uri, isSearch) {
|
||||
var message = {
|
||||
message: commands.MG_NAVIGATE,
|
||||
args: {
|
||||
uri: uri,
|
||||
encodedSearchURI: isSearch ? uri : getSearchURI(uri)
|
||||
}
|
||||
};
|
||||
|
||||
window.chrome.webview.postMessage(message);
|
||||
}
|
||||
|
||||
function reloadActiveTabContent() {
|
||||
var message = {
|
||||
message: commands.MG_RELOAD,
|
||||
args: {}
|
||||
};
|
||||
window.chrome.webview.postMessage(message);
|
||||
}
|
||||
|
||||
function containsIlegalCharacters(query) {
|
||||
return !VALID_URI_REGEX.test(query);
|
||||
}
|
||||
|
||||
function isSingleWord(query) {
|
||||
return WORD_REGEX.test(query);
|
||||
}
|
||||
|
||||
function hasScheme(query) {
|
||||
return SCHEMED_URI_REGEX.test(query);
|
||||
}
|
||||
|
||||
function getSearchURI(query) {
|
||||
return `https://www.bing.com/search?q=${encodeURIComponent(query)}`;
|
||||
}
|
||||
|
||||
function closeWindow() {
|
||||
var message = {
|
||||
message: commands.MG_CLOSE_WINDOW,
|
||||
args: {}
|
||||
};
|
||||
|
||||
window.chrome.webview.postMessage(message);
|
||||
}
|
||||
|
||||
// Show active tab's URI in the address bar
|
||||
function updateURI() {
|
||||
if (activeTabId == INVALID_TAB_ID) {
|
||||
return;
|
||||
}
|
||||
|
||||
let activeTab = tabs.get(activeTabId);
|
||||
document.getElementById('address-field').value = activeTab.uriToShow || activeTab.uri;
|
||||
}
|
||||
|
||||
// Show active tab's favicon in the address bar
|
||||
function updateFavicon() {
|
||||
if (activeTabId == INVALID_TAB_ID) {
|
||||
return;
|
||||
}
|
||||
|
||||
let activeTab = tabs.get(activeTabId);
|
||||
|
||||
let faviconElement = document.getElementById('img-favicon');
|
||||
if (!faviconElement) {
|
||||
refreshControls();
|
||||
return;
|
||||
}
|
||||
|
||||
faviconElement.src = activeTab.favicon;
|
||||
|
||||
}
|
||||
|
||||
// Update back and forward buttons for the active tab
|
||||
function updateBackForwardButtons() {
|
||||
if (activeTabId == INVALID_TAB_ID) {
|
||||
return;
|
||||
}
|
||||
|
||||
let activeTab = tabs.get(activeTabId);
|
||||
let btnForward = document.getElementById('btn-forward');
|
||||
let btnBack = document.getElementById('btn-back');
|
||||
|
||||
if (!btnBack || !btnForward) {
|
||||
refreshControls();
|
||||
return;
|
||||
}
|
||||
|
||||
if (activeTab.canGoForward)
|
||||
btnForward.className = 'btn';
|
||||
else
|
||||
btnForward.className = 'btn-disabled';
|
||||
|
||||
if (activeTab.canGoBack)
|
||||
btnBack.className = 'btn';
|
||||
else
|
||||
btnBack.className = 'btn-disabled';
|
||||
}
|
||||
|
||||
// Update reload button for the active tab
|
||||
function updateReloadButton() {
|
||||
if (activeTabId == INVALID_TAB_ID) {
|
||||
return;
|
||||
}
|
||||
|
||||
let activeTab = tabs.get(activeTabId);
|
||||
|
||||
let btnReload = document.getElementById('btn-reload');
|
||||
if (!btnReload) {
|
||||
refreshControls();
|
||||
return;
|
||||
}
|
||||
|
||||
btnReload.className = activeTab.isLoading ? 'btn-cancel' : 'btn';
|
||||
}
|
||||
|
||||
// Update lock icon for the active tab
|
||||
function updateLockIcon() {
|
||||
if (activeTabId == INVALID_TAB_ID) {
|
||||
return;
|
||||
}
|
||||
|
||||
let activeTab = tabs.get(activeTabId);
|
||||
|
||||
let labelElement = document.getElementById('security-label');
|
||||
if (!labelElement) {
|
||||
refreshControls();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (activeTab.securityState) {
|
||||
case 'insecure':
|
||||
labelElement.className = 'label-insecure';
|
||||
break;
|
||||
case 'neutral':
|
||||
labelElement.className = 'label-neutral';
|
||||
break;
|
||||
case 'secure':
|
||||
labelElement.className = 'label-secure';
|
||||
break;
|
||||
default:
|
||||
labelElement.className = 'label-unknown';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update favorite status for the active tab
|
||||
function updateFavoriteIcon() {
|
||||
if (activeTabId == INVALID_TAB_ID) {
|
||||
return;
|
||||
}
|
||||
|
||||
let activeTab = tabs.get(activeTabId);
|
||||
isFavorite(activeTab.uri, (isFavorite) => {
|
||||
let favoriteElement = document.getElementById('btn-fav');
|
||||
if (!favoriteElement) {
|
||||
refreshControls();
|
||||
return;
|
||||
}
|
||||
|
||||
if (isFavorite) {
|
||||
favoriteElement.classList.add('favorited');
|
||||
activeTab.isFavorite = true;
|
||||
} else {
|
||||
favoriteElement.classList.remove('favorited');
|
||||
activeTab.isFavorite = false;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function updateNavigationUI(reason) {
|
||||
switch (reason) {
|
||||
case commands.MG_UPDATE_URI:
|
||||
updateURI();
|
||||
updateFavoriteIcon();
|
||||
updateBackForwardButtons();
|
||||
break;
|
||||
case commands.MG_NAV_COMPLETED:
|
||||
case commands.MG_NAV_STARTING:
|
||||
updateReloadButton();
|
||||
break;
|
||||
case commands.MG_SECURITY_UPDATE:
|
||||
updateLockIcon();
|
||||
break;
|
||||
case commands.MG_UPDATE_FAVICON:
|
||||
updateFavicon();
|
||||
break;
|
||||
// If a reason is not provided (for requests not originating from a
|
||||
// message), default to switch tab behavior.
|
||||
default:
|
||||
case commands.MG_SWITCH_TAB:
|
||||
updateURI();
|
||||
updateLockIcon();
|
||||
updateFavicon();
|
||||
updateFavoriteIcon();
|
||||
updateReloadButton();
|
||||
updateBackForwardButtons();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function loadTabUI(tabId) {
|
||||
if (isValidTabId(tabId)) {
|
||||
let tab = tabs.get(tabId);
|
||||
|
||||
let tabElement = document.createElement('div');
|
||||
tabElement.className = tabId == activeTabId ? 'tab-active' : 'tab';
|
||||
tabElement.id = `tab-${tabId}`;
|
||||
|
||||
let tabLabel = document.createElement('div');
|
||||
tabLabel.className = 'tab-label';
|
||||
|
||||
let labelText = document.createElement('span');
|
||||
labelText.textContent = tab.title;
|
||||
tabLabel.appendChild(labelText);
|
||||
|
||||
let closeButton = document.createElement('div');
|
||||
closeButton.className = 'btn-tab-close';
|
||||
closeButton.addEventListener('click', function(e) {
|
||||
closeTab(tabId);
|
||||
});
|
||||
|
||||
tabElement.appendChild(tabLabel);
|
||||
tabElement.appendChild(closeButton);
|
||||
|
||||
var createTabButton = document.getElementById('btn-new-tab');
|
||||
document.getElementById('tabs-strip').insertBefore(tabElement, createTabButton);
|
||||
|
||||
tabElement.addEventListener('click', function(e) {
|
||||
if (e.srcElement.className != 'btn-tab-close') {
|
||||
switchToTab(tabId, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function toggleOptionsDropdown() {
|
||||
const optionsButtonElement = document.getElementById('btn-options');
|
||||
const elementClass = optionsButtonElement.className;
|
||||
|
||||
var message;
|
||||
if (elementClass === 'btn') {
|
||||
// Update UI
|
||||
optionsButtonElement.className = 'btn-active';
|
||||
|
||||
message = {
|
||||
message: commands.MG_SHOW_OPTIONS,
|
||||
args: {}
|
||||
};
|
||||
} else {
|
||||
// Update UI
|
||||
optionsButtonElement.className = 'btn';
|
||||
|
||||
message = {
|
||||
message:commands.MG_HIDE_OPTIONS,
|
||||
args: {}
|
||||
};
|
||||
}
|
||||
|
||||
window.chrome.webview.postMessage(message);
|
||||
}
|
||||
|
||||
function refreshControls() {
|
||||
let controlsElement = document.getElementById('controls-bar');
|
||||
if (controlsElement) {
|
||||
controlsElement.remove();
|
||||
}
|
||||
|
||||
controlsElement = document.createElement('div');
|
||||
controlsElement.id = 'controls-bar';
|
||||
|
||||
// Navigation controls
|
||||
let navControls = document.createElement('div');
|
||||
navControls.className = 'controls-group';
|
||||
navControls.id = 'nav-controls-container';
|
||||
|
||||
let backButton = document.createElement('div');
|
||||
backButton.className = 'btn-disabled';
|
||||
backButton.id = 'btn-back';
|
||||
navControls.append(backButton);
|
||||
|
||||
let forwardButton = document.createElement('div');
|
||||
forwardButton.className = 'btn-disabled';
|
||||
forwardButton.id = 'btn-forward';
|
||||
navControls.append(forwardButton);
|
||||
|
||||
let reloadButton = document.createElement('div');
|
||||
reloadButton.className = 'btn';
|
||||
reloadButton.id = 'btn-reload';
|
||||
navControls.append(reloadButton);
|
||||
|
||||
controlsElement.append(navControls);
|
||||
|
||||
// Address bar
|
||||
let addressBar = document.createElement('div');
|
||||
addressBar.id = 'address-bar-container';
|
||||
|
||||
let securityLabel = document.createElement('div');
|
||||
securityLabel.className = 'label-unknown';
|
||||
securityLabel.id = 'security-label';
|
||||
|
||||
let labelSpan = document.createElement('span');
|
||||
labelSpan.textContent = 'Not secure';
|
||||
securityLabel.append(labelSpan);
|
||||
|
||||
let lockIcon = document.createElement('div');
|
||||
lockIcon.className = 'icn';
|
||||
lockIcon.id = 'icn-lock';
|
||||
securityLabel.append(lockIcon);
|
||||
addressBar.append(securityLabel);
|
||||
|
||||
let faviconElement = document.createElement('div');
|
||||
faviconElement.className = 'icn';
|
||||
faviconElement.id = 'icn-favicon';
|
||||
|
||||
let faviconImage = document.createElement('img');
|
||||
faviconImage.id = 'img-favicon';
|
||||
faviconImage.src = 'img/favicon.png';
|
||||
faviconElement.append(faviconImage);
|
||||
addressBar.append(faviconElement);
|
||||
|
||||
let addressInput = document.createElement('input');
|
||||
addressInput.id = 'address-field';
|
||||
addressInput.placeholder = 'Search or enter web address';
|
||||
addressInput.type = 'text';
|
||||
addressInput.spellcheck = false;
|
||||
addressBar.append(addressInput);
|
||||
|
||||
let clearButton = document.createElement('button');
|
||||
clearButton.id = 'btn-clear';
|
||||
addressBar.append(clearButton);
|
||||
|
||||
let favoriteButton = document.createElement('div');
|
||||
favoriteButton.className = 'icn';
|
||||
favoriteButton.id = 'btn-fav';
|
||||
addressBar.append(favoriteButton);
|
||||
controlsElement.append(addressBar);
|
||||
|
||||
// Manage controls
|
||||
let manageControls = document.createElement('div');
|
||||
manageControls.className = 'controls-group';
|
||||
manageControls.id = 'manage-controls-container';
|
||||
|
||||
let optionsButton = document.createElement('div');
|
||||
optionsButton.className = 'btn';
|
||||
optionsButton.id = 'btn-options';
|
||||
manageControls.append(optionsButton);
|
||||
controlsElement.append(manageControls);
|
||||
|
||||
// Insert controls bar into document
|
||||
let tabsElement = document.getElementById('tabs-strip');
|
||||
if (tabsElement) {
|
||||
tabsElement.parentElement.insertBefore(controlsElement, tabsElement);
|
||||
} else {
|
||||
let bodyElement = document.getElementsByTagName('body')[0];
|
||||
bodyElement.append(controlsElement);
|
||||
}
|
||||
|
||||
addControlsListeners();
|
||||
updateNavigationUI();
|
||||
}
|
||||
|
||||
function refreshTabs() {
|
||||
let tabsStrip = document.getElementById('tabs-strip');
|
||||
if (tabsStrip) {
|
||||
tabsStrip.remove();
|
||||
}
|
||||
|
||||
tabsStrip = document.createElement('div');
|
||||
tabsStrip.id = 'tabs-strip';
|
||||
|
||||
let newTabButton = document.createElement('div');
|
||||
newTabButton.id = 'btn-new-tab';
|
||||
|
||||
let buttonSpan = document.createElement('span');
|
||||
buttonSpan.textContent = '+';
|
||||
buttonSpan.id = 'plus-label';
|
||||
newTabButton.append(buttonSpan);
|
||||
tabsStrip.append(newTabButton);
|
||||
|
||||
let bodyElement = document.getElementsByTagName('body')[0];
|
||||
bodyElement.append(tabsStrip);
|
||||
|
||||
addTabsListeners();
|
||||
|
||||
Array.from(tabs).map((tabEntry) => {
|
||||
loadTabUI(tabEntry[0]);
|
||||
});
|
||||
}
|
||||
|
||||
function toggleFavorite() {
|
||||
activeTab = tabs.get(activeTabId);
|
||||
if (activeTab.isFavorite) {
|
||||
removeFavorite(activeTab.uri, () => {
|
||||
activeTab.isFavorite = false;
|
||||
updateFavoriteIcon();
|
||||
});
|
||||
} else {
|
||||
addFavorite(favoriteFromTab(activeTabId), () => {
|
||||
activeTab.isFavorite = true;
|
||||
updateFavoriteIcon();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function addControlsListeners() {
|
||||
let inputField = document.querySelector('#address-field');
|
||||
let clearButton = document.querySelector('#btn-clear');
|
||||
|
||||
inputField.addEventListener('keypress', function(e) {
|
||||
var key = e.which || e.keyCode;
|
||||
if (key === 13) { // 13 is enter
|
||||
e.preventDefault();
|
||||
processAddressBarInput();
|
||||
}
|
||||
});
|
||||
|
||||
inputField.addEventListener('focus', function(e) {
|
||||
e.target.select();
|
||||
});
|
||||
|
||||
inputField.addEventListener('blur', function(e) {
|
||||
inputField.setSelectionRange(0, 0);
|
||||
if (!inputField.value) {
|
||||
updateURI();
|
||||
}
|
||||
});
|
||||
|
||||
clearButton.addEventListener('click', function(e) {
|
||||
inputField.value = '';
|
||||
inputField.focus();
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
document.querySelector('#btn-forward').addEventListener('click', function(e) {
|
||||
if (document.getElementById('btn-forward').className === 'btn') {
|
||||
var message = {
|
||||
message: commands.MG_GO_FORWARD,
|
||||
args: {}
|
||||
};
|
||||
window.chrome.webview.postMessage(message);
|
||||
}
|
||||
});
|
||||
|
||||
document.querySelector('#btn-back').addEventListener('click', function(e) {
|
||||
if (document.getElementById('btn-back').className === 'btn') {
|
||||
var message = {
|
||||
message: commands.MG_GO_BACK,
|
||||
args: {}
|
||||
};
|
||||
window.chrome.webview.postMessage(message);
|
||||
}
|
||||
});
|
||||
|
||||
document.querySelector('#btn-reload').addEventListener('click', function(e) {
|
||||
var btnReload = document.getElementById('btn-reload');
|
||||
if (btnReload.className === 'btn-cancel') {
|
||||
var message = {
|
||||
message: commands.MG_CANCEL,
|
||||
args: {}
|
||||
};
|
||||
window.chrome.webview.postMessage(message);
|
||||
} else if (btnReload.className === 'btn') {
|
||||
reloadActiveTabContent();
|
||||
}
|
||||
});
|
||||
|
||||
document.querySelector('#btn-options').addEventListener('click', function(e) {
|
||||
toggleOptionsDropdown();
|
||||
});
|
||||
|
||||
window.onkeydown = function(event) {
|
||||
if (event.ctrlKey) {
|
||||
switch (event.key) {
|
||||
case 'r':
|
||||
case 'R':
|
||||
reloadActiveTabContent();
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
toggleFavorite();
|
||||
break;
|
||||
case 't':
|
||||
case 'T':
|
||||
createNewTab(true);
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
case '+':
|
||||
case '-':
|
||||
case '_':
|
||||
case '=':
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
// Prevent zooming the UI
|
||||
window.addEventListener('wheel', function(event) {
|
||||
if (event.ctrlKey) {
|
||||
event.preventDefault();
|
||||
}}, { passive: false });
|
||||
}
|
||||
|
||||
function addTabsListeners() {
|
||||
document.querySelector('#btn-new-tab').addEventListener('click', function(e) {
|
||||
createNewTab(true);
|
||||
});
|
||||
|
||||
document.querySelector('#btn-fav').addEventListener('click', function(e) {
|
||||
toggleFavorite();
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
window.chrome.webview.addEventListener('message', messageHandler);
|
||||
refreshControls();
|
||||
refreshTabs();
|
||||
|
||||
createNewTab(true);
|
||||
}
|
||||
|
||||
init();
|
||||
72
assets/wvbrowser_ui/controls_ui/favorites.js
Normal file
@ -0,0 +1,72 @@
|
||||
function isFavorite(uri, callback) {
|
||||
queryDB((db) => {
|
||||
let transaction = db.transaction(['favorites']);
|
||||
let favoritesStore = transaction.objectStore('favorites');
|
||||
let favoriteStatusRequest = favoritesStore.get(uri);
|
||||
|
||||
favoriteStatusRequest.onerror = function(event) {
|
||||
console.log(`Could not query for ${uri}: ${event.target.error.message}`);
|
||||
};
|
||||
|
||||
favoriteStatusRequest.onsuccess = function() {
|
||||
callback(favoriteStatusRequest.result);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function addFavorite(favorite, callback) {
|
||||
queryDB((db) => {
|
||||
let transaction = db.transaction(['favorites'], 'readwrite');
|
||||
let favoritesStore = transaction.objectStore('favorites');
|
||||
let addFavoriteRequest = favoritesStore.add(favorite);
|
||||
|
||||
addFavoriteRequest.onerror = function(event) {
|
||||
console.log(`Could not add favorite with key: ${favorite.uri}`);
|
||||
console.log(event.target.error.message);
|
||||
};
|
||||
|
||||
addFavoriteRequest.onsuccess = function(event) {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function removeFavorite(key, callback) {
|
||||
queryDB((db) => {
|
||||
let transaction = db.transaction(['favorites'], 'readwrite');
|
||||
let favoritesStore = transaction.objectStore('favorites');
|
||||
let removeFavoriteRequest = favoritesStore.delete(key);
|
||||
|
||||
removeFavoriteRequest.onerror = function(event) {
|
||||
console.log(`Could not remove favorite with key: ${key}`);
|
||||
console.log(event.target.error.message);
|
||||
};
|
||||
|
||||
removeFavoriteRequest.onsuccess = function(event) {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function getFavoritesAsJson(callback) {
|
||||
queryDB((db) => {
|
||||
let transaction = db.transaction(['favorites']);
|
||||
let favoritesStore = transaction.objectStore('favorites');
|
||||
let getFavoritesRequest = favoritesStore.getAll();
|
||||
|
||||
getFavoritesRequest.onerror = function(event) {
|
||||
console.log(`Could retrieve favorites`);
|
||||
console.log(event.target.error.message);
|
||||
};
|
||||
|
||||
getFavoritesRequest.onsuccess = function(event) {
|
||||
if (callback) {
|
||||
callback(getFavoritesRequest.result);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
143
assets/wvbrowser_ui/controls_ui/history.js
Normal file
@ -0,0 +1,143 @@
|
||||
const INVALID_HISTORY_ID = -1;
|
||||
|
||||
function addHistoryItem(item, callback) {
|
||||
queryDB((db) => {
|
||||
let transaction = db.transaction(['history'], 'readwrite');
|
||||
let historyStore = transaction.objectStore('history');
|
||||
|
||||
// Check if an item for this URI exists on this day
|
||||
let currentDate = new Date();
|
||||
let year = currentDate.getFullYear();
|
||||
let month = currentDate.getMonth();
|
||||
let date = currentDate.getDate();
|
||||
let todayDate = new Date(year, month, date);
|
||||
|
||||
let existingItemsIndex = historyStore.index('stampedURI');
|
||||
let lowerBound = [item.uri, todayDate];
|
||||
let upperBound = [item.uri, currentDate];
|
||||
let range = IDBKeyRange.bound(lowerBound, upperBound);
|
||||
let request = existingItemsIndex.openCursor(range);
|
||||
|
||||
request.onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
// There's an entry for this URI, update the item
|
||||
cursor.value.timestamp = item.timestamp;
|
||||
let updateRequest = cursor.update(cursor.value);
|
||||
|
||||
updateRequest.onsuccess = function(event) {
|
||||
if (callback) {
|
||||
callback(event.target.result.primaryKey);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
// No entry for this URI, add item
|
||||
let addItemRequest = historyStore.add(item);
|
||||
|
||||
addItemRequest.onsuccess = function(event) {
|
||||
if (callback) {
|
||||
callback(event.target.result);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function updateHistoryItem(id, item, callback) {
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
|
||||
queryDB((db) => {
|
||||
let transaction = db.transaction(['history'], 'readwrite');
|
||||
let historyStore = transaction.objectStore('history');
|
||||
let storedItemRequest = historyStore.get(id);
|
||||
storedItemRequest.onsuccess = function(event) {
|
||||
let storedItem = event.target.result;
|
||||
item.timestamp = storedItem.timestamp;
|
||||
|
||||
let updateRequest = historyStore.put(item, id);
|
||||
|
||||
updateRequest.onsuccess = function(event) {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function getHistoryItems(from, n, callback) {
|
||||
if (n <= 0 || from < 0) {
|
||||
if (callback) {
|
||||
callback([]);
|
||||
}
|
||||
}
|
||||
|
||||
queryDB((db) => {
|
||||
let transaction = db.transaction(['history']);
|
||||
let historyStore = transaction.objectStore('history');
|
||||
let timestampIndex = historyStore.index('timestamp');
|
||||
let cursorRequest = timestampIndex.openCursor(null, 'prev');
|
||||
|
||||
let current = 0;
|
||||
let items = [];
|
||||
cursorRequest.onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
|
||||
if (!cursor || current >= from + n) {
|
||||
if (callback) {
|
||||
callback(items);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (current >= from) {
|
||||
items.push({
|
||||
id: cursor.primaryKey,
|
||||
item: cursor.value
|
||||
});
|
||||
}
|
||||
|
||||
++current;
|
||||
cursor.continue();
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function removeHistoryItem(id, callback) {
|
||||
queryDB((db) => {
|
||||
let transaction = db.transaction(['history'], 'readwrite');
|
||||
let historyStore = transaction.objectStore('history');
|
||||
let removeItemRequest = historyStore.delete(id);
|
||||
|
||||
removeItemRequest.onerror = function(event) {
|
||||
console.log(`Could not remove history item with ID: ${id}`);
|
||||
console.log(event.target.error.message);
|
||||
};
|
||||
|
||||
removeItemRequest.onsuccess = function(event) {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function clearHistory(callback) {
|
||||
queryDB((db) => {
|
||||
let transaction = db.transaction(['history'], 'readwrite');
|
||||
let historyStore = transaction.objectStore('history');
|
||||
let clearRequest = historyStore.clear();
|
||||
|
||||
clearRequest.onsuccess = function(event) {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
BIN
assets/wvbrowser_ui/controls_ui/img/cancel.png
Normal file
|
After Width: | Height: | Size: 696 B |
BIN
assets/wvbrowser_ui/controls_ui/img/favicon.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
assets/wvbrowser_ui/controls_ui/img/favorite.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
assets/wvbrowser_ui/controls_ui/img/favorited.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
assets/wvbrowser_ui/controls_ui/img/goBack.png
Normal file
|
After Width: | Height: | Size: 458 B |
BIN
assets/wvbrowser_ui/controls_ui/img/goBack_disabled.png
Normal file
|
After Width: | Height: | Size: 472 B |
BIN
assets/wvbrowser_ui/controls_ui/img/goForward.png
Normal file
|
After Width: | Height: | Size: 479 B |
BIN
assets/wvbrowser_ui/controls_ui/img/goForward_disabled.png
Normal file
|
After Width: | Height: | Size: 479 B |
BIN
assets/wvbrowser_ui/controls_ui/img/insecure.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
assets/wvbrowser_ui/controls_ui/img/neutral.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/wvbrowser_ui/controls_ui/img/options.png
Normal file
|
After Width: | Height: | Size: 417 B |
BIN
assets/wvbrowser_ui/controls_ui/img/reload.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
assets/wvbrowser_ui/controls_ui/img/secure.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/wvbrowser_ui/controls_ui/img/unknown.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
38
assets/wvbrowser_ui/controls_ui/options.css
Normal file
@ -0,0 +1,38 @@
|
||||
html, body {
|
||||
width: 200px;
|
||||
height: 107px;
|
||||
}
|
||||
|
||||
#dropdown-wrapper {
|
||||
width: calc(100% - 2px);
|
||||
height: calc(100% - 2px);
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
background-color: rgb(240, 240, 240);
|
||||
}
|
||||
|
||||
.dropdown-item:hover {
|
||||
background-color: rgb(220, 220, 220);
|
||||
}
|
||||
|
||||
.item-label {
|
||||
display: flex;
|
||||
height: 35px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.item-label span {
|
||||
font-family: Arial;
|
||||
font-size: 0.8em;
|
||||
vertical-align: middle;
|
||||
flex: 1;
|
||||
align-self: center;
|
||||
text-align: left;
|
||||
padding-left: 10px;
|
||||
}
|
||||
28
assets/wvbrowser_ui/controls_ui/options.html
Normal file
@ -0,0 +1,28 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<link rel="stylesheet" type="text/css" href="options.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="dropdown-wrapper">
|
||||
<div id="item-settings" class="dropdown-item">
|
||||
<div class="item-label">
|
||||
<span>Settings</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="item-history" class="dropdown-item">
|
||||
<div class="item-label">
|
||||
<span>History</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="item-favorites" class="dropdown-item">
|
||||
<div class="item-label">
|
||||
<span>Favorites</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="../commands.js"></script>
|
||||
<script src="options.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
46
assets/wvbrowser_ui/controls_ui/options.js
Normal file
@ -0,0 +1,46 @@
|
||||
function navigateToBrowserPage(path) {
|
||||
const navMessage = {
|
||||
message: commands.MG_NAVIGATE,
|
||||
args: {
|
||||
uri: `browser://${path}`
|
||||
}
|
||||
};
|
||||
|
||||
window.chrome.webview.postMessage(navMessage);
|
||||
}
|
||||
|
||||
// Add listener for the options menu entries
|
||||
function addItemsListeners() {
|
||||
|
||||
// Close dropdown when item is selected
|
||||
(() => {
|
||||
const dropdownItems = Array.from(document.getElementsByClassName('dropdown-item'));
|
||||
dropdownItems.map(item => {
|
||||
item.addEventListener('click', function(e) {
|
||||
const closeMessage = {
|
||||
message: commands.MG_OPTION_SELECTED,
|
||||
args: {}
|
||||
};
|
||||
window.chrome.webview.postMessage(closeMessage);
|
||||
});
|
||||
|
||||
// Navigate to browser page
|
||||
let entry = item.id.split('-')[1];
|
||||
switch (entry) {
|
||||
case 'settings':
|
||||
case 'history':
|
||||
case 'favorites':
|
||||
item.addEventListener('click', function(e) {
|
||||
navigateToBrowserPage(entry);
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
})();
|
||||
}
|
||||
|
||||
function init() {
|
||||
addItemsListeners();
|
||||
}
|
||||
|
||||
init();
|
||||
44
assets/wvbrowser_ui/controls_ui/storage.js
Normal file
@ -0,0 +1,44 @@
|
||||
function handleUpgradeEvent(event) {
|
||||
console.log('Creating DB');
|
||||
let newDB = event.target.result;
|
||||
|
||||
newDB.onerror = function(event) {
|
||||
console.log('Something went wrong');
|
||||
console.log(event);
|
||||
};
|
||||
|
||||
let newFavoritesStore = newDB.createObjectStore('favorites', {
|
||||
keyPath: 'uri'
|
||||
});
|
||||
|
||||
newFavoritesStore.transaction.oncomplete = function(event) {
|
||||
console.log('Object stores created');
|
||||
};
|
||||
|
||||
let newHistoryStore = newDB.createObjectStore('history', {
|
||||
autoIncrement: true
|
||||
});
|
||||
|
||||
newHistoryStore.createIndex('timestamp', 'timestamp', {
|
||||
unique: false
|
||||
});
|
||||
|
||||
newHistoryStore.createIndex('stampedURI', ['uri', 'timestamp'], {
|
||||
unique: false
|
||||
});
|
||||
}
|
||||
|
||||
function queryDB(query) {
|
||||
let request = window.indexedDB.open('WVBrowser');
|
||||
|
||||
request.onerror = function(event) {
|
||||
console.log('Failed to open database');
|
||||
};
|
||||
|
||||
request.onsuccess = function(event) {
|
||||
let db = event.target.result;
|
||||
query(db);
|
||||
};
|
||||
|
||||
request.onupgradeneeded = handleUpgradeEvent;
|
||||
}
|
||||
72
assets/wvbrowser_ui/controls_ui/strip.css
Normal file
@ -0,0 +1,72 @@
|
||||
#tabs-strip {
|
||||
display: flex;
|
||||
height: 28px;
|
||||
|
||||
border-top: 1px solid rgb(200, 200, 200);
|
||||
border-bottom: 1px solid rgb(200, 200, 200);
|
||||
background-color: rgb(230, 230, 230);
|
||||
}
|
||||
|
||||
.tab, .tab-active {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
border-right: 1px solid rgb(200, 200, 200);
|
||||
overflow: hidden;
|
||||
max-width: 250px;
|
||||
}
|
||||
|
||||
.tab-active {
|
||||
background-color: rgb(240, 240, 240);
|
||||
}
|
||||
|
||||
#btn-new-tab {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
#btn-new-tab:hover, .btn-tab-close:hover {
|
||||
background-color: rgb(200, 200, 200);
|
||||
}
|
||||
|
||||
#plus-label {
|
||||
display: block;
|
||||
flex: 1;
|
||||
align-self: center;
|
||||
line-height: 30px;
|
||||
width: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn-tab-close {
|
||||
display: inline-block;
|
||||
align-self: center;
|
||||
min-width: 16px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 0 5px;
|
||||
border-radius: 4px;
|
||||
|
||||
background-size: 100%;
|
||||
background-image: url('img/cancel.png');
|
||||
}
|
||||
|
||||
.tab-label {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
padding: 5px;
|
||||
padding-left: 10px;
|
||||
height: calc(100% - 10px);
|
||||
vertical-align: middle;
|
||||
|
||||
white-space:nowrap;
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
.tab-label span {
|
||||
font-family: Arial;
|
||||
font-size: 0.8em;
|
||||
flex: 1;
|
||||
align-self: center;
|
||||
}
|
||||
13
assets/wvbrowser_ui/controls_ui/styles.css
Normal file
@ -0,0 +1,13 @@
|
||||
html, body {
|
||||
margin: 0;
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
* {
|
||||
user-select: none;
|
||||
}
|
||||
216
assets/wvbrowser_ui/controls_ui/tabs.js
Normal file
@ -0,0 +1,216 @@
|
||||
var tabs = new Map();
|
||||
var tabIdCounter = 0;
|
||||
var activeTabId = 0;
|
||||
const INVALID_TAB_ID = 0;
|
||||
|
||||
function getNewTabId() {
|
||||
return ++tabIdCounter;
|
||||
}
|
||||
|
||||
function isValidTabId(tabId) {
|
||||
return tabId != INVALID_TAB_ID && tabs.has(tabId);
|
||||
}
|
||||
|
||||
function createNewTab(shouldBeActive) {
|
||||
const tabId = getNewTabId();
|
||||
|
||||
var message = {
|
||||
message: commands.MG_CREATE_TAB,
|
||||
args: {
|
||||
tabId: parseInt(tabId),
|
||||
active: shouldBeActive || false
|
||||
}
|
||||
};
|
||||
|
||||
window.chrome.webview.postMessage(message);
|
||||
|
||||
tabs.set(parseInt(tabId), {
|
||||
title: 'New Tab',
|
||||
uri: '',
|
||||
uriToShow: '',
|
||||
favicon: 'img/favicon.png',
|
||||
isFavorite: false,
|
||||
isLoading: false,
|
||||
canGoBack: false,
|
||||
canGoForward: false,
|
||||
securityState: 'unknown',
|
||||
historyItemId: INVALID_HISTORY_ID
|
||||
});
|
||||
|
||||
loadTabUI(tabId);
|
||||
|
||||
if (shouldBeActive) {
|
||||
switchToTab(tabId, false);
|
||||
}
|
||||
}
|
||||
|
||||
function switchToTab(id, updateOnHost) {
|
||||
if (!id) {
|
||||
console.log('ID not provided');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the tab to switch to is valid
|
||||
if (!isValidTabId(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// No need to switch if the tab is already active
|
||||
if (id == activeTabId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the tab element to switch to
|
||||
var tab = document.getElementById(`tab-${id}`);
|
||||
if (!tab) {
|
||||
console.log(`Can't switch to tab ${id}: element does not exist`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Change the style for the previously active tab
|
||||
if (isValidTabId(activeTabId)) {
|
||||
const activeTabElement = document.getElementById(`tab-${activeTabId}`);
|
||||
|
||||
// Check the previously active tab element does actually exist
|
||||
if (activeTabElement) {
|
||||
activeTabElement.className = 'tab';
|
||||
}
|
||||
}
|
||||
|
||||
// Set tab as active
|
||||
tab.className = 'tab-active';
|
||||
activeTabId = id;
|
||||
|
||||
// Instruct host app to switch tab
|
||||
if (updateOnHost) {
|
||||
var message = {
|
||||
message: commands.MG_SWITCH_TAB,
|
||||
args: {
|
||||
tabId: parseInt(activeTabId)
|
||||
}
|
||||
};
|
||||
|
||||
window.chrome.webview.postMessage(message);
|
||||
}
|
||||
|
||||
updateNavigationUI(commands.MG_SWITCH_TAB);
|
||||
}
|
||||
|
||||
function closeTab(id) {
|
||||
// If closing tab was active, switch tab or close window
|
||||
if (id == activeTabId) {
|
||||
if (tabs.size == 1) {
|
||||
// Last tab is closing, shut window down
|
||||
tabs.delete(id);
|
||||
closeWindow();
|
||||
return;
|
||||
}
|
||||
|
||||
// Other tabs are open, switch to rightmost tab
|
||||
var tabsEntries = Array.from(tabs.entries());
|
||||
var lastEntry = tabsEntries.pop();
|
||||
if (lastEntry[0] == id) {
|
||||
lastEntry = tabsEntries.pop();
|
||||
}
|
||||
switchToTab(lastEntry[0], true);
|
||||
}
|
||||
|
||||
// Remove tab element
|
||||
var tabElement = document.getElementById(`tab-${id}`);
|
||||
if (tabElement) {
|
||||
tabElement.parentNode.removeChild(tabElement);
|
||||
}
|
||||
// Remove tab from map
|
||||
tabs.delete(id);
|
||||
|
||||
var message = {
|
||||
message: commands.MG_CLOSE_TAB,
|
||||
args: {
|
||||
tabId: id
|
||||
}
|
||||
};
|
||||
|
||||
window.chrome.webview.postMessage(message);
|
||||
}
|
||||
|
||||
function updateFaviconURI(tabId, src) {
|
||||
let tab = tabs.get(tabId);
|
||||
if (tab.favicon != src) {
|
||||
let img = new Image();
|
||||
|
||||
// Update favicon element on successful load
|
||||
img.onload = () => {
|
||||
console.log('Favicon loaded');
|
||||
tab.favicon = src;
|
||||
|
||||
if (tabId == activeTabId) {
|
||||
updatedFaviconURIHandler(tabId, tab);
|
||||
}
|
||||
};
|
||||
|
||||
if (src) {
|
||||
// Try load from root on failed load
|
||||
img.onerror = () => {
|
||||
console.log('Cannot load favicon from link, trying with root');
|
||||
updateFaviconURI(tabId, '');
|
||||
};
|
||||
} else {
|
||||
// No link for favicon, try loading from root
|
||||
try {
|
||||
let tabURI = new URL(tab.uri);
|
||||
src = `${tabURI.origin}/favicon.ico`;
|
||||
} catch(e) {
|
||||
console.log(`Could not parse tab ${tabId} URI`);
|
||||
}
|
||||
|
||||
img.onerror = () => {
|
||||
console.log('No favicon in site root. Using default favicon.');
|
||||
tab.favicon = 'img/favicon.png';
|
||||
updatedFaviconURIHandler(tabId, tab);
|
||||
};
|
||||
}
|
||||
|
||||
img.src = src;
|
||||
}
|
||||
}
|
||||
|
||||
function updatedFaviconURIHandler(tabId, tab) {
|
||||
updateNavigationUI(commands.MG_UPDATE_FAVICON);
|
||||
|
||||
// Update favicon in history item
|
||||
if (tab.historyItemId != INVALID_HISTORY_ID) {
|
||||
updateHistoryItem(tab.historyItemId, historyItemFromTab(tabId));
|
||||
}
|
||||
}
|
||||
|
||||
function favoriteFromTab(tabId) {
|
||||
if (!isValidTabId(tabId)) {
|
||||
console.log('Invalid tab ID');
|
||||
return;
|
||||
}
|
||||
|
||||
let tab = tabs.get(tabId);
|
||||
let favicon = tab.favicon == 'img/favicon.png' ? '../controls_ui/' + tab.favicon : tab.favicon;
|
||||
return {
|
||||
uri: tab.uri,
|
||||
uriToShow: tab.uriToShow,
|
||||
title: tab.title,
|
||||
favicon: favicon
|
||||
};
|
||||
}
|
||||
|
||||
function historyItemFromTab(tabId) {
|
||||
if (!isValidTabId(tabId)) {
|
||||
console.log('Invalid tab ID');
|
||||
return;
|
||||
}
|
||||
|
||||
let tab = tabs.get(tabId);
|
||||
let favicon = tab.favicon == 'img/favicon.png' ? '../controls_ui/' + tab.favicon : tab.favicon;
|
||||
return {
|
||||
uri: tab.uri,
|
||||
title: tab.title,
|
||||
favicon: favicon,
|
||||
timestamp: new Date()
|
||||
}
|
||||
}
|
||||
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/.signature.p7s
vendored
Normal file
27
packages/Microsoft.Web.WebView2.1.0.961.33/LICENSE.txt
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* The name of Microsoft Corporation, or the names of its contributors
|
||||
may not be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/Microsoft.Web.WebView2.1.0.961.33.nupkg
vendored
Normal file
5178
packages/Microsoft.Web.WebView2.1.0.961.33/WebView2.idl
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/WebView2.tlb
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/Common.targets
vendored
Normal file
23
packages/Microsoft.Web.WebView2.1.0.961.33/build/Microsoft.Web.WebView2.targets
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0"?>
|
||||
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<!-- This build/.targets file is used by managed VS projects including win32
|
||||
apps and UWP apps. -->
|
||||
|
||||
<PropertyGroup>
|
||||
<WebView2ProjectKind>managed</WebView2ProjectKind>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- The managed targets file is under build
|
||||
so the root is one path segment up. -->
|
||||
<NugetRoot>$(MSBuildThisFileDirectory)..\</NugetRoot>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Example logging
|
||||
<Target Name="WebView2ManagedEntryLog" BeforeTargets="Build">
|
||||
<Message Text="WebView2 managed .targets file. $(NugetRoot)" Importance="high"/>
|
||||
</Target>
|
||||
-->
|
||||
|
||||
<Import Project="$(NugetRoot)\build\Common.targets"/>
|
||||
</Project>
|
||||
22
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/Microsoft.Web.WebView2.targets
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0"?>
|
||||
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<!-- This build\native\.targets file is used by native (C++) VS projects including win32 and UWP. -->
|
||||
|
||||
<PropertyGroup>
|
||||
<WebView2ProjectKind>native</WebView2ProjectKind>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- The native targets file is under build\native
|
||||
so the root is two path segments up. -->
|
||||
<NugetRoot>$(MSBuildThisFileDirectory)..\..\</NugetRoot>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Example logging
|
||||
<Target Name="WebView2NativeEntryLog" BeforeTargets="Build">
|
||||
<Message Text="WebView2 native .targets file. $(NugetRoot)" Importance="high"/>
|
||||
</Target>
|
||||
-->
|
||||
|
||||
<Import Project="$(NugetRoot)\build\Common.targets"/>
|
||||
</Project>
|
||||
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/arm64/WebView2Loader.dll
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/arm64/WebView2Loader.dll.lib
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/arm64/WebView2LoaderStatic.lib
vendored
Normal file
16558
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/include/WebView2.h
vendored
Normal file
144
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/include/WebView2EnvironmentOptions.h
vendored
Normal file
@ -0,0 +1,144 @@
|
||||
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef __core_webview2_environment_options_h__
|
||||
#define __core_webview2_environment_options_h__
|
||||
|
||||
#include <objbase.h>
|
||||
#include <wrl/implements.h>
|
||||
|
||||
#include "webview2.h"
|
||||
#define CORE_WEBVIEW_TARGET_PRODUCT_VERSION L"93.0.961.33"
|
||||
|
||||
#define COREWEBVIEW2ENVIRONMENTOPTIONS_STRING_PROPERTY(p) \
|
||||
public: \
|
||||
HRESULT STDMETHODCALLTYPE get_##p(LPWSTR* value) override { \
|
||||
if (!value) \
|
||||
return E_POINTER; \
|
||||
*value = m_##p.Copy(); \
|
||||
if ((*value == nullptr) && (m_##p.Get() != nullptr)) \
|
||||
return HRESULT_FROM_WIN32(GetLastError()); \
|
||||
return S_OK; \
|
||||
} \
|
||||
HRESULT STDMETHODCALLTYPE put_##p(LPCWSTR value) override { \
|
||||
LPCWSTR result = m_##p.Set(value); \
|
||||
if ((result == nullptr) && (value != nullptr)) \
|
||||
return HRESULT_FROM_WIN32(GetLastError()); \
|
||||
return S_OK; \
|
||||
} \
|
||||
\
|
||||
protected: \
|
||||
AutoCoMemString m_##p;
|
||||
|
||||
#define COREWEBVIEW2ENVIRONMENTOPTIONS_BOOL_PROPERTY(p) \
|
||||
public: \
|
||||
HRESULT STDMETHODCALLTYPE get_##p(BOOL* value) override { \
|
||||
if (!value) \
|
||||
return E_POINTER; \
|
||||
*value = m_##p; \
|
||||
return S_OK; \
|
||||
} \
|
||||
HRESULT STDMETHODCALLTYPE put_##p(BOOL value) override { \
|
||||
m_##p = value; \
|
||||
return S_OK; \
|
||||
} \
|
||||
\
|
||||
protected: \
|
||||
BOOL m_##p = FALSE;
|
||||
|
||||
// This is a base COM class that implements ICoreWebView2EnvironmentOptions.
|
||||
template <typename allocate_fn_t,
|
||||
allocate_fn_t allocate_fn,
|
||||
typename deallocate_fn_t,
|
||||
deallocate_fn_t deallocate_fn>
|
||||
class CoreWebView2EnvironmentOptionsBase
|
||||
: public Microsoft::WRL::Implements<
|
||||
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
|
||||
ICoreWebView2EnvironmentOptions> {
|
||||
public:
|
||||
CoreWebView2EnvironmentOptionsBase() {
|
||||
// Initialize the target compatible browser version value to the version of
|
||||
// the browser binaries corresponding to this version of the SDK.
|
||||
m_TargetCompatibleBrowserVersion.Set(CORE_WEBVIEW_TARGET_PRODUCT_VERSION);
|
||||
}
|
||||
|
||||
protected:
|
||||
~CoreWebView2EnvironmentOptionsBase(){};
|
||||
|
||||
class AutoCoMemString {
|
||||
public:
|
||||
AutoCoMemString() {}
|
||||
~AutoCoMemString() { Release(); }
|
||||
void Release() {
|
||||
if (m_string) {
|
||||
deallocate_fn(m_string);
|
||||
m_string = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
LPCWSTR Set(LPCWSTR str) {
|
||||
Release();
|
||||
if (str) {
|
||||
m_string = MakeCoMemString(str);
|
||||
}
|
||||
return m_string;
|
||||
}
|
||||
LPCWSTR Get() { return m_string; }
|
||||
LPWSTR Copy() {
|
||||
if (m_string)
|
||||
return MakeCoMemString(m_string);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
LPWSTR MakeCoMemString(LPCWSTR source) {
|
||||
const size_t length = wcslen(source);
|
||||
const size_t bytes = (length + 1) * sizeof(*source);
|
||||
// Ensure we didn't overflow during our size calculation.
|
||||
if (bytes <= length) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wchar_t* result = reinterpret_cast<wchar_t*>(allocate_fn(bytes));
|
||||
if (result)
|
||||
memcpy(result, source, bytes);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
LPWSTR m_string = nullptr;
|
||||
};
|
||||
|
||||
COREWEBVIEW2ENVIRONMENTOPTIONS_STRING_PROPERTY(AdditionalBrowserArguments)
|
||||
COREWEBVIEW2ENVIRONMENTOPTIONS_STRING_PROPERTY(Language)
|
||||
COREWEBVIEW2ENVIRONMENTOPTIONS_STRING_PROPERTY(TargetCompatibleBrowserVersion)
|
||||
COREWEBVIEW2ENVIRONMENTOPTIONS_BOOL_PROPERTY(
|
||||
AllowSingleSignOnUsingOSPrimaryAccount)
|
||||
};
|
||||
|
||||
template <typename allocate_fn_t,
|
||||
allocate_fn_t allocate_fn,
|
||||
typename deallocate_fn_t,
|
||||
deallocate_fn_t deallocate_fn>
|
||||
class CoreWebView2EnvironmentOptionsBaseClass
|
||||
: public Microsoft::WRL::RuntimeClass<
|
||||
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
|
||||
CoreWebView2EnvironmentOptionsBase<allocate_fn_t,
|
||||
allocate_fn,
|
||||
deallocate_fn_t,
|
||||
deallocate_fn>> {
|
||||
public:
|
||||
CoreWebView2EnvironmentOptionsBaseClass() {}
|
||||
|
||||
protected:
|
||||
~CoreWebView2EnvironmentOptionsBaseClass() override{};
|
||||
};
|
||||
|
||||
typedef CoreWebView2EnvironmentOptionsBaseClass<decltype(&::CoTaskMemAlloc),
|
||||
::CoTaskMemAlloc,
|
||||
decltype(&::CoTaskMemFree),
|
||||
::CoTaskMemFree>
|
||||
CoreWebView2EnvironmentOptions;
|
||||
|
||||
#endif // __core_webview2_environment_options_h__
|
||||
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x64/WebView2Loader.dll
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x64/WebView2Loader.dll.lib
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x64/WebView2LoaderStatic.lib
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x86/WebView2Loader.dll
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x86/WebView2Loader.dll.lib
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/build/native/x86/WebView2LoaderStatic.lib
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/Microsoft.Web.WebView2.Core.winmd
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/net45/Microsoft.Web.WebView2.Core.dll
vendored
Normal file
4456
packages/Microsoft.Web.WebView2.1.0.961.33/lib/net45/Microsoft.Web.WebView2.Core.xml
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/net45/Microsoft.Web.WebView2.WinForms.dll
vendored
Normal file
375
packages/Microsoft.Web.WebView2.1.0.961.33/lib/net45/Microsoft.Web.WebView2.WinForms.xml
vendored
Normal file
@ -0,0 +1,375 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>Microsoft.Web.WebView2.WinForms</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties">
|
||||
<summary>
|
||||
This class is a bundle of the most common parameters used to create a <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/>.
|
||||
Its main purpose is to be set to <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CreationProperties"/> in order to customize the environment used by a <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/> during implicit initialization.
|
||||
</summary>
|
||||
<remarks>
|
||||
This class isn't intended to contain all possible environment customization options.
|
||||
If you need complete control over the environment used by a WebView2 control then you'll need to initialize the control explicitly by
|
||||
creating your own environment with <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> and passing it to <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/>
|
||||
*before* you set the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property to anything.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/> class documentation for an initialization overview.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.#ctor">
|
||||
<summary>
|
||||
Creates a new instance of <see cref="T:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties"/> with default data for all properties.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.BrowserExecutableFolder">
|
||||
<summary>
|
||||
Gets or sets the value to pass as the browserExecutableFolder parameter of <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.UserDataFolder">
|
||||
<summary>
|
||||
Gets or sets the value to pass as the userDataFolder parameter of <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.Language">
|
||||
<summary>
|
||||
Gets or sets the value to use for the Language property of the CoreWebView2EnvironmentOptions parameter passed to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.CreateEnvironmentAsync">
|
||||
<summary>
|
||||
Create a <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> using the current values of this instance's properties.
|
||||
</summary>
|
||||
<returns>A task which will provide the created environment on completion.</returns>
|
||||
<remarks>
|
||||
As long as no other properties on this instance are changed, repeated calls to this method will return the same task/environment as earlier calls.
|
||||
If some other property is changed then the next call to this method will return a different task/environment.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="T:Microsoft.Web.WebView2.WinForms.WebView2">
|
||||
<summary>
|
||||
Control to embed WebView2 in WinForms.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.#ctor">
|
||||
<summary>
|
||||
Create a new WebView2 WinForms control.
|
||||
After construction the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> property is <c>null</c>.
|
||||
Call <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> to initialize the underlying <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/>.
|
||||
</summary>
|
||||
<remarks>
|
||||
This control is effectively a wrapper around the WebView2 COM API, which you can find documentation for here: https://aka.ms/webview2
|
||||
You can directly access the underlying ICoreWebView2 interface and all of its functionality by accessing the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> property.
|
||||
Some of the most common COM functionality is also accessible directly through wrapper methods/properties/events on the control.
|
||||
|
||||
Upon creation, the control's CoreWebView2 property will be null.
|
||||
This is because creating the CoreWebView2 is an expensive operation which involves things like launching Edge browser processes.
|
||||
There are two ways to cause the CoreWebView2 to be created:
|
||||
1) Call the <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> method. This is referred to as explicit initialization.
|
||||
2) Set the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property. This is referred to as implicit initialization.
|
||||
Either option will start initialization in the background and return back to the caller without waiting for it to finish.
|
||||
To specify options regarding the initialization process, either pass your own <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> to EnsureCoreWebView2Async or set the control's <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CreationProperties"/> property prior to initialization.
|
||||
|
||||
When initialization has finished (regardless of how it was triggered) then the following things will occur, in this order:
|
||||
1) The control's <see cref="E:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2InitializationCompleted"/> event will be invoked. If you need to perform one time setup operations on the CoreWebView2 prior to its use then you should do so in a handler for that event.
|
||||
2) If a Uri has been set to the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property then the control will start navigating to it in the background (i.e. these steps will continue without waiting for the navigation to finish).
|
||||
3) The Task returned from <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> will complete.
|
||||
|
||||
For more details about any of the methods/properties/events involved in the initialization process, see its specific documentation.
|
||||
|
||||
Accelerator key presses (e.g. Ctrl+P) that occur within the control will
|
||||
fire standard key press events such as OnKeyDown. You can suppress the
|
||||
control's default implementation of an accelerator key press (e.g.
|
||||
printing, in the case of Ctrl+P) by setting the Handled property of its
|
||||
EventArgs to true. Also note that the underlying browser process is
|
||||
blocked while these handlers execute, so:
|
||||
<list type="number">
|
||||
<item>
|
||||
You should avoid doing a lot of work in these handlers.
|
||||
</item>
|
||||
<item>
|
||||
Some of the WebView2 and CoreWebView2 APIs may throw errors if
|
||||
invoked within these handlers due to being unable to communicate with
|
||||
the browser process.
|
||||
</item>
|
||||
</list>
|
||||
If you need to do a lot of work and/or invoke WebView2 APIs in response to
|
||||
accelerator keys then consider kicking off a background task or queuing
|
||||
the work for later execution on the UI thread.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.Dispose(System.Boolean)">
|
||||
<summary>
|
||||
Cleans up any resources being used.
|
||||
</summary>
|
||||
<param name="disposing"><c>true</c> if managed resources should be disposed; otherwise, <c>false</c>.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.OnPaint(System.Windows.Forms.PaintEventArgs)">
|
||||
<summary>
|
||||
Overrides the base OnPaint event to have custom actions
|
||||
in designer mode
|
||||
</summary>
|
||||
<param name="e">The graphics devices which is the source</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.WndProc(System.Windows.Forms.Message@)">
|
||||
<summary>
|
||||
Overrides the base WndProc events to handle specific window messages.
|
||||
</summary>
|
||||
<param name="m">The Message object containing the HWND window message and parameters</param>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CreationProperties">
|
||||
<summary>
|
||||
Gets or sets a bag of options which are used during initialization of the control's <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/>.
|
||||
This property cannot be modified (an exception will be thrown) after initialization of the control's CoreWebView2 has started.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown if initialization of the control's CoreWebView2 has already started.</exception>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)">
|
||||
<summary>
|
||||
Explicitly trigger initialization of the control's <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/>.
|
||||
</summary>
|
||||
<param name="environment">
|
||||
A pre-created <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> that should be used to create the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/>.
|
||||
Creating your own environment gives you control over several options that affect how the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is initialized.
|
||||
If you pass <c>null</c> (the default value) then a default environment will be created and used automatically.
|
||||
</param>
|
||||
<returns>
|
||||
A Task that represents the background initialization process.
|
||||
When the task completes then the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> property will be available for use (i.e. non-null).
|
||||
Note that the control's <see cref="E:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2InitializationCompleted"/> event will be invoked before the task completes
|
||||
or on exceptions.
|
||||
</returns>
|
||||
<remarks>
|
||||
Calling this method additional times will have no effect (any specified environment is ignored) and return the same Task as the first call.
|
||||
Calling this method after initialization has been implicitly triggered by setting the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property will have no effect (any specified environment is ignored) and simply return a Task representing that initialization already in progress.
|
||||
</remarks>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if this instance of <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is already disposed, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="P:System.Windows.Forms.Control.InvokeRequired"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.InitCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)">
|
||||
<summary>
|
||||
This is the private function which implements the actual background initialization task.
|
||||
Cannot be called if the control is already initialized or has been disposed.
|
||||
</summary>
|
||||
<param name="environment">
|
||||
The environment to use to create the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Controller"/>.
|
||||
If that is null then a default environment is created with <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> and its default parameters.
|
||||
</param>
|
||||
<returns>A task representing the background initialization process.</returns>
|
||||
<remarks>All the event handlers added here need to be removed in <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.Dispose(System.Boolean)"/>.</remarks>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CreateParams">
|
||||
<summary>
|
||||
Protected CreateParams property. Used to set custom window styles to the forms HWND.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.OnVisibleChanged(System.EventArgs)">
|
||||
<summary>
|
||||
Protected VisibilityChanged handler.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.OnSizeChanged(System.EventArgs)">
|
||||
<summary>
|
||||
Protected SizeChanged handler.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.Select(System.Boolean,System.Boolean)">
|
||||
<summary>
|
||||
Protected Select method: override this to capture tab direction when WebView control is activated
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.OnGotFocus(System.EventArgs)">
|
||||
<summary>
|
||||
Protected OnGotFocus handler.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.IsInitialized">
|
||||
<summary>
|
||||
True if initialization finished successfully and the control is not disposed yet.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.GetSitedParentSite(System.Windows.Forms.Control)">
|
||||
<summary>
|
||||
Recursive retrieval of the parent control
|
||||
</summary>
|
||||
<param name="control">The control to get the parent for</param>
|
||||
<returns>The root parent control</returns>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2">
|
||||
<summary>
|
||||
The underlying CoreWebView2. Use this property to perform more operations on the WebView2 content than is exposed
|
||||
on the WebView2. This value is null until it is initialized and the object itself has undefined behaviour once the control is disposed.
|
||||
You can force the underlying CoreWebView2 to
|
||||
initialize via the <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> method.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="P:System.Windows.Forms.Control.InvokeRequired"/> for more info.</exception>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.ZoomFactor">
|
||||
<summary>
|
||||
The zoom factor for the WebView.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.Source">
|
||||
<summary>
|
||||
The Source property is the URI of the top level document of the
|
||||
WebView2. Setting the Source is equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Navigate(System.String)"/>.
|
||||
Setting the Source will trigger initialization of the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/>, if not already initialized.
|
||||
The default value of Source is <c>null</c>, indicating that the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized.
|
||||
</summary>
|
||||
<exception cref="T:System.ArgumentException">Specified value is not an absolute <see cref="T:System.Uri"/>.</exception>
|
||||
<exception cref="T:System.NotImplementedException">Specified value is <c>null</c> and the control is initialized.</exception>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Navigate(System.String)"/>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CanGoForward">
|
||||
<summary>
|
||||
Returns true if the webview can navigate to a next page in the
|
||||
navigation history via the <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.GoForward"/> method.
|
||||
This is equivalent to the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoForward"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this property is <c>false</c>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoForward"/>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CanGoBack">
|
||||
<summary>
|
||||
Returns <c>true</c> if the webview can navigate to a previous page in the
|
||||
navigation history via the <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.GoBack"/> method.
|
||||
This is equivalent to the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this property is <c>false</c>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.DefaultBackgroundColor">
|
||||
<summary>
|
||||
The default background color for the WebView.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.ExecuteScriptAsync(System.String)">
|
||||
<summary>
|
||||
Executes the provided script in the top level document of the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.ExecuteScriptAsync(System.String)"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">The underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized.</exception>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown when browser process has unexpectedly and left this control in an invalid state. We are considering throwing a different type of exception for this case in the future.</exception>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.ExecuteScriptAsync(System.String)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.Reload">
|
||||
<summary>
|
||||
Reloads the top level document of the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Reload"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">The underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized.</exception>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown when browser process has unexpectedly and left this control in an invalid state. We are considering throwing a different type of exception for this case in the future.</exception>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Reload"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.GoForward">
|
||||
<summary>
|
||||
Navigates to the next page in navigation history.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoForward"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this method does nothing.
|
||||
</summary>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoForward"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.GoBack">
|
||||
<summary>
|
||||
Navigates to the previous page in navigation history.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoBack"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this method does nothing.
|
||||
</summary>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoBack"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.NavigateToString(System.String)">
|
||||
<summary>
|
||||
Renders the provided HTML as the top level document of the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.NavigateToString(System.String)"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">The underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized.</exception>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown when browser process has unexpectedly and left this control in an invalid state. We are considering throwing a different type of exception for this case in the future.</exception>
|
||||
<remarks>The <c>htmlContent</c> parameter may not be larger than 2 MB (2 * 1024 * 1024 bytes) in total size. The origin of the new page is <c>about:blank</c>.</remarks>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.NavigateToString(System.String)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.Stop">
|
||||
<summary>
|
||||
Stops any in progress navigation in the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Stop"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this method does nothing.
|
||||
</summary>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Stop"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2InitializationCompleted">
|
||||
<summary>
|
||||
This event is triggered either 1) when the control's <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> has finished being initialized (regardless of how it was triggered or whether it succeeded) but before it is used for anything
|
||||
OR 2) the initialization failed.
|
||||
You should handle this event if you need to perform one time setup operations on the CoreWebView2 which you want to affect all of its usages
|
||||
(e.g. adding event handlers, configuring settings, installing document creation scripts, adding host objects).
|
||||
</summary>
|
||||
<remarks>
|
||||
This sender will be the WebView2 control, whose CoreWebView2 property will now be valid (i.e. non-null) for the first time
|
||||
if <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs.IsSuccess"/> is true.
|
||||
Unlikely this event can fire second time (after reporting initialization success first)
|
||||
if the initialization is followed by navigation which fails.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.NavigationStarting">
|
||||
<summary>
|
||||
NavigationStarting dispatches before a new navigate starts for the top
|
||||
level document of the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.NavigationCompleted">
|
||||
<summary>
|
||||
NavigationCompleted dispatches after a navigate of the top level
|
||||
document completes rendering either successfully or not.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.WebMessageReceived">
|
||||
<summary>
|
||||
WebMessageReceived dispatches after web content sends a message to the
|
||||
app host via <c>chrome.webview.postMessage</c>.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.SourceChanged">
|
||||
<summary>
|
||||
SourceChanged dispatches after the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property changes. This may happen
|
||||
during a navigation or if otherwise the script in the page changes the
|
||||
URI of the document.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.ContentLoading">
|
||||
<summary>
|
||||
ContentLoading dispatches after a navigation begins to a new URI and the
|
||||
content of that URI begins to render.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.ZoomFactorChanged">
|
||||
<summary>
|
||||
ZoomFactorChanged dispatches when the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.ZoomFactor"/> property changes.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactorChanged"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactorChanged"/>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.WinForms.WebView2.components">
|
||||
<summary>
|
||||
Required designer variable.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.InitializeComponent">
|
||||
<summary>
|
||||
Required method for Designer support - do not modify
|
||||
the contents of this method with the code editor.
|
||||
</summary>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/net45/Microsoft.Web.WebView2.Wpf.dll
vendored
Normal file
800
packages/Microsoft.Web.WebView2.1.0.961.33/lib/net45/Microsoft.Web.WebView2.Wpf.xml
vendored
Normal file
@ -0,0 +1,800 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>Microsoft.Web.WebView2.Wpf</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties">
|
||||
<summary>
|
||||
This class is a bundle of the most common parameters used to create a <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/>.
|
||||
Its main purpose is to be set to <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> in order to customize the environment used by a <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> during implicit initialization.
|
||||
It is also a nice WPF integration utility which allows commonly used environment parameters to be dependency properties and be created and used in markup.
|
||||
</summary>
|
||||
<remarks>
|
||||
This class isn't intended to contain all possible environment customization options.
|
||||
If you need complete control over the environment used by a WebView2 control then you'll need to initialize the control explicitly by
|
||||
creating your own environment with <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> and passing it to <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/>
|
||||
*before* you set the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property to anything.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.#ctor">
|
||||
<summary>
|
||||
Creates a new instance of <see cref="T:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties"/> with default data for all properties.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.BrowserExecutableFolderProperty">
|
||||
<summary>
|
||||
The WPF DependencyProperty which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.BrowserExecutableFolder"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.BrowserExecutableFolder">
|
||||
<summary>
|
||||
Gets or sets the value to pass as the browserExecutableFolder parameter of <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.UserDataFolderProperty">
|
||||
<summary>
|
||||
The WPF DependencyProperty which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.UserDataFolder"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.UserDataFolder">
|
||||
<summary>
|
||||
Gets or sets the value to pass as the userDataFolder parameter of <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.LanguageProperty">
|
||||
<summary>
|
||||
The WPF DependencyProperty which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.Language"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.Language">
|
||||
<summary>
|
||||
Gets or sets the value to use for the Language property of the CoreWebView2EnvironmentOptions parameter passed to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.CreateEnvironmentAsync">
|
||||
<summary>
|
||||
Create a <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> using the current values of this instance's properties.
|
||||
</summary>
|
||||
<returns>A task which will provide the created environment on completion.</returns>
|
||||
<remarks>
|
||||
As long as no other properties on this instance are changed, repeated calls to this method will return the same task/environment as earlier calls.
|
||||
If some other property is changed then the next call to this method will return a different task/environment.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="T:Microsoft.Web.WebView2.Wpf.WebView2">
|
||||
<summary>
|
||||
A control to embed web content in a WPF application.
|
||||
</summary>
|
||||
<remarks>
|
||||
This control is effectively a wrapper around the [WebView2 COM
|
||||
API](https://aka.ms/webview2). You can directly access the underlying
|
||||
ICoreWebView2 interface and all of its functionality by accessing the
|
||||
<see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> property. Some of the most common COM
|
||||
functionality is also accessible directly through wrapper
|
||||
methods/properties/events on the control.
|
||||
|
||||
Upon creation, the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> property will be
|
||||
<c>null</c>. This is because creating the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> is an
|
||||
expensive operation which involves things like launching Edge browser
|
||||
processes. There are two ways to cause the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> to
|
||||
be created:
|
||||
<list type="bullet">
|
||||
<item><description>
|
||||
Call the <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> method. This is
|
||||
referred to as explicit initialization.
|
||||
</description></item>
|
||||
<item><description>
|
||||
Set the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property (which could be done from
|
||||
markup, for example). This is referred to as implicit initialization.
|
||||
Either option will start initialization in the background and return
|
||||
back to the caller without waiting for it to finish.
|
||||
To specify options regarding the initialization process, either pass
|
||||
your own <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> to <see
|
||||
cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> or set the control's <see
|
||||
cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> property prior to initialization.
|
||||
</description></item>
|
||||
</list>
|
||||
|
||||
When initialization has finished (regardless of how it was triggered or
|
||||
whether it succeeded) then the following things will occur, in this
|
||||
order:
|
||||
<list type="number">
|
||||
<item><description>
|
||||
The control's <see cref="E:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2InitializationCompleted"/> event
|
||||
will be invoked. If you need to perform one time setup operations on
|
||||
the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> prior to its use then you should
|
||||
do so in a handler for that event.
|
||||
</description></item>
|
||||
<item><description>
|
||||
If initialization was successful and a Uri has been set to the <see
|
||||
cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property then the control will start navigating to it in
|
||||
the background (i.e. these steps will continue without waiting for the
|
||||
navigation to finish).
|
||||
</description></item>
|
||||
<item><description>
|
||||
The Task returned from <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> will
|
||||
complete.
|
||||
</description></item>
|
||||
</list>
|
||||
|
||||
For more details about any of the methods/properties/events involved in
|
||||
the initialization process, see its specific documentation.
|
||||
|
||||
Because the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> is a very heavyweight
|
||||
object (potentially responsible for multiple running processes and
|
||||
megabytes of disk space) the control implements <see
|
||||
cref="T:System.IDisposable"/> to provide an explicit means to free it.
|
||||
Calling <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> will release the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>
|
||||
and its underlying resources (except any that are also being used by other
|
||||
WebViews), and reset <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> to <c>null</c>. After <see
|
||||
cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has been called the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> cannot be
|
||||
re-initialized, and any attempt to use functionality which requires it
|
||||
will throw an <see cref="T:System.ObjectDisposedException"/>.
|
||||
|
||||
Accelerator key presses (e.g. Ctrl+P) that occur within the control will
|
||||
fire standard key press events such as OnKeyDown. You can suppress the
|
||||
control's default implementation of an accelerator key press (e.g.
|
||||
printing, in the case of Ctrl+P) by setting the Handled property of its
|
||||
EventArgs to true. Also note that the underlying browser process is
|
||||
blocked while these handlers execute, so:
|
||||
<list type="number">
|
||||
<item>
|
||||
<description>You should avoid doing a lot of work in these handlers.</description>
|
||||
</item>
|
||||
<item><description>
|
||||
Some of the WebView2 and CoreWebView2 APIs may throw errors if
|
||||
invoked within these handlers due to being unable to communicate with
|
||||
the browser process.
|
||||
</description></item>
|
||||
</list>
|
||||
If you need to do a lot of work and/or invoke WebView2 APIs in response to
|
||||
accelerator keys then consider kicking off a background task or queuing
|
||||
the work for later execution on the UI thread.
|
||||
|
||||
Note that this control extends <see cref="T:System.Windows.Interop.HwndHost"/> in order to embed
|
||||
windows which live outside of the WPF ecosystem. This has some
|
||||
implications regarding the control's input and output behavior as well as
|
||||
the functionality it "inherits" from <see cref="T:System.Windows.UIElement"/> and <see
|
||||
cref="T:System.Windows.FrameworkElement"/>.
|
||||
See the <see cref="T:System.Windows.Interop.HwndHost"/> and [WPF/Win32
|
||||
interop](https://docs.microsoft.com/dotnet/framework/wpf/advanced/wpf-and-win32-interoperation#hwnds-inside-wpf)
|
||||
documentation for more information.
|
||||
</remarks>
|
||||
<seealso cref="T:System.Windows.Interop.HwndHost"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.#ctor">
|
||||
<summary>
|
||||
Creates a new instance of a WebView2 control.
|
||||
Note that the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> will be null until initialized.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.CreationPropertiesProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> property.
|
||||
</summary>
|
||||
<seealso cref="T:System.Windows.DependencyProperty"/>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties">
|
||||
<summary>
|
||||
Gets or sets a bag of options which are used during initialization of the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
Setting this property will not work after initialization of the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> has started (the old value will be retained).
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.BuildWindowCore(System.Runtime.InteropServices.HandleRef)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and is called to instruct us to create our HWND.
|
||||
</summary>
|
||||
<param name="hwndParent">The HWND that we should use as the parent of the one we create.</param>
|
||||
<returns>The HWND that we created.</returns>
|
||||
<seealso cref="M:System.Windows.Interop.HwndHost.BuildWindowCore(System.Runtime.InteropServices.HandleRef)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.DestroyWindowCore(System.Runtime.InteropServices.HandleRef)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and is called to instruct us to destroy our HWND.
|
||||
</summary>
|
||||
<param name="hwnd">Our HWND that we need to destroy.</param>
|
||||
<seealso cref="M:System.Windows.Interop.HwndHost.DestroyWindowCore(System.Runtime.InteropServices.HandleRef)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.WndProc(System.IntPtr,System.Int32,System.IntPtr,System.IntPtr,System.Boolean@)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and is called to provide us with Win32 messages that are sent to our hwnd.
|
||||
</summary>
|
||||
<param name="hwnd">Window receiving the message (should always match our <see cref="P:System.Windows.Interop.HwndHost.Handle"/>).</param>
|
||||
<param name="msg">Indicates the message being received. See Win32 documentation for WM_* constant values.</param>
|
||||
<param name="wParam">The "wParam" data being provided with the message. Meaning varies by message.</param>
|
||||
<param name="lParam">The "lParam" data being provided with the message. Meaning varies by message.</param>
|
||||
<param name="handled">If true then the message will not be forwarded to any (more) <see cref="E:System.Windows.Interop.HwndHost.MessageHook"/> handlers.</param>
|
||||
<returns>Return value varies by message.</returns>
|
||||
<seealso cref="M:System.Windows.Interop.HwndHost.WndProc(System.IntPtr,System.Int32,System.IntPtr,System.IntPtr,System.Boolean@)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnRender(System.Windows.Media.DrawingContext)">
|
||||
<summary>
|
||||
Override for painting to draw
|
||||
</summary>
|
||||
<param name="dc">The tools to handle the drawing via <see cref="T:System.Windows.Media.DrawingContext"/>.</param>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2">
|
||||
<summary>
|
||||
Accesses the complete functionality of the underlying <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> COM API.
|
||||
Returns <c>null</c> until initialization has completed.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2InitializationCompleted">
|
||||
<summary>
|
||||
This event is triggered either
|
||||
1) when the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> has finished being initialized (regardless of how initialization was triggered) but before it is used for anything, or
|
||||
2) if the initialization failed.
|
||||
You should handle this event if you need to perform one time setup operations on the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> which you want to affect all of its usages.
|
||||
(e.g. adding event handlers, configuring settings, installing document creation scripts, adding host objects).
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
<remarks>
|
||||
This sender will be the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whose <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> property will now be valid (i.e. non-null) for the first time
|
||||
if <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs.IsSuccess"/> is <c>true</c>.
|
||||
Unlikely this event can fire second time (after reporting initialization success first)
|
||||
if the initialization is followed by navigation which fails.
|
||||
</remarks>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)">
|
||||
<summary>
|
||||
Explicitly triggers initialization of the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
<param name="environment">
|
||||
A pre-created <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> that should be used to create the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/>.
|
||||
Creating your own environment gives you control over several options that affect how the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> is initialized.
|
||||
If you pass an environment to this method then it will override any settings specified on the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> property.
|
||||
If you pass <c>null</c> (the default value) and no value has been set to <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> then a default environment will be created and used automatically.
|
||||
</param>
|
||||
<returns>
|
||||
A Task that represents the background initialization process.
|
||||
When the task completes then the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> property will be available for use (i.e. non-null).
|
||||
Note that the control's <see cref="E:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2InitializationCompleted"/> event will be invoked before the task completes.
|
||||
</returns>
|
||||
<remarks>
|
||||
Calling this method additional times will have no effect (any specified environment is ignored) and return the same Task as the first call.
|
||||
Calling this method after initialization has been implicitly triggered by setting the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property will have no effect (any specified environment is ignored) and simply return a Task representing that initialization already in progress.
|
||||
Note that even though this method is asynchronous and returns a Task, it still must be called on the UI thread like most public functionality of most UI controls.
|
||||
</remarks>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)">
|
||||
<summary>
|
||||
This is called by our base class according to the typical implementation of the <see cref="T:System.IDisposable"/> pattern.
|
||||
We implement it by releasing all of our underlying COM resources, including our <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
</summary>
|
||||
<param name="disposing">True if a caller is explicitly calling Dispose, false if we're being finalized.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_ProcessFailed(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2ProcessFailedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's ProcessFailedEvent
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.BeginInit">
|
||||
<summary>
|
||||
Implementation of the ISupportInitialize pattern.
|
||||
Prevents the control from implicitly initializing its <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> until <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EndInit"/> is called.
|
||||
Does *not* prevent explicit initialization of the CoreWebView2 (i.e. <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/>).
|
||||
Mainly intended for use by interactive UI designers.
|
||||
</summary>
|
||||
<remarks>
|
||||
Note that the "Initialize" in ISupportInitialize and the "Init" in BeginInit/EndInit mean
|
||||
something different and more general than this control's specific concept of initializing
|
||||
its CoreWebView2 (explicitly or implicitly). This ISupportInitialize pattern is a general
|
||||
way to set batches of properties on the control to their initial values without triggering
|
||||
any dependent side effects until all of the values are set (i.e. until EndInit is called).
|
||||
In the case of this control, a specific side effect to be avoided is triggering implicit
|
||||
initialization of the CoreWebView2 when setting the Source property.
|
||||
For example, normally if you set <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> after you've already set Source,
|
||||
the data set to CreationProperties is ignored because implicit initialization has already started.
|
||||
However, if you set the two properties (in the same order) in between calls to BeginInit and
|
||||
EndInit then the implicit initialization of the CoreWebView2 is delayed until EndInit, so the data
|
||||
set to CreationProperties is still used even though it was set after Source.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.EndInit">
|
||||
<summary>
|
||||
Implementation of the ISupportInitialize pattern.
|
||||
Invokes any functionality that has been delayed since the corresponding call to <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.BeginInit"/>.
|
||||
Mainly intended for use by interactive UI designers.
|
||||
</summary>
|
||||
<remarks>
|
||||
See the documentation of <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.BeginInit"/> for more information.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.WhenInit_Source(System.Action)">
|
||||
<summary>
|
||||
Specifies a Source-related action to be invoked but which must be delayed if BeginInit has already been called but EndInit hasn't.
|
||||
If the control is currently between BeginInit/EndInit calls then the action will be invoked during EndInit.
|
||||
Otherwise the action will be invoked immediately.
|
||||
If this is called multiple times between BeginInit/EndInit then the action passed to the last call is the only one that will be invoked during EndInit.
|
||||
</summary>
|
||||
<param name="action">The Source-related action to invoke, delayed until EndInit if necessary.</param>
|
||||
<remarks>
|
||||
In the future if we need this delayed-invoke functionality for actions unrelated to Source,
|
||||
then we should generalize _initAction_Source to a list and generalize this method to take a list index along with the action.
|
||||
Then we can just assign each index to a different potential action (e.g. 0 for Source), and potentially use constants to name the indices.
|
||||
For now it didn't seem worth dynamically allocating a list for one thing,
|
||||
but I still wanted to keep the delay-or-not logic abstracted away from the Source setter.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.SetCurrentValueFromCore(System.Windows.DependencyProperty,System.Object)">
|
||||
<summary>
|
||||
Updates one of our dependency properties to match a new value from the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
It both sets the value and remembers (in _propertyChangingFromCore) that it came from the CoreWebView2 rather than the caller,
|
||||
allowing the property's "on changed" handler to alter its behavior based on where the new value came from.
|
||||
It's only intended to be called in a CoreWebView2 event handler that's informing us of a new property value.
|
||||
It's basically just a wrapper around the inherited SetCurrentValue which also maintains _propertyChangingFromCore.
|
||||
See the comments on <see cref="F:Microsoft.Web.WebView2.Wpf.WebView2._propertyChangingFromCore"/> for additional background info.
|
||||
One more thing worth explicitly stating is that it wraps SetCurrentValue rather than SetValue,
|
||||
in order to avoid overwriting any OneWay bindings that are set on the specified properties.
|
||||
Check the link https://stackoverflow.com/q/4230698 for more information about the difference between SetValue and SetCurrentValue.
|
||||
</summary>
|
||||
<param name="property">The property to change due to an equivalent change in the CoreWebView2.</param>
|
||||
<param name="value">The new value from the CoreWebView2.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.IsPropertyChangingFromCore(System.Windows.DependencyProperty)">
|
||||
<summary>
|
||||
Checks if a given property is currently being updated to match an equivalent change in the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
This method should only be called from a property's "on changed" handler; it has no meaning at any other time.
|
||||
It is used to determine if the property is changing to match the CoreWebView2 or because the caller set it.
|
||||
Usually this is used in order to decide if the new value needs to be propagated down to the CoreWebView2.
|
||||
See the comments on <see cref="F:Microsoft.Web.WebView2.Wpf.WebView2._propertyChangingFromCore"/> for additional background info.
|
||||
</summary>
|
||||
<param name="property">The property to check.</param>
|
||||
<returns>True if the property is changing to match the CoreWebView2, or false if the property was changed by the caller.</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.ReparentController(System.IntPtr,System.Boolean)">
|
||||
<summary>
|
||||
Changes our controller's ParentWindow to the given HWND, along with any other necessary associated work.
|
||||
</summary>
|
||||
<param name="hwnd">The new HWND to set as the controller's parent. IntPtr.Zero means that the controller will have no parent and the CoreWebView2 will be hidden.</param>
|
||||
<param name="sync">Whether or not to call <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.SyncControllerWithParentWindow"/> as required. Defaults to true. If you pass false then you should call it yourself if required.</param>
|
||||
<remarks>
|
||||
Reparenting the controller isn't necessarily as simple as changing its ParentWindow property,
|
||||
and this method exists to ensure that any other work that needs to be done at the same time gets done.
|
||||
The reason that SyncControllerWithParentWindow isn't baked directly into this method is because
|
||||
sometimes we want to call the Sync functionality without necessarily reparenting (e.g. during initialization).
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.SyncControllerWithParentWindow">
|
||||
<summary>
|
||||
Syncs visual/windowing information between the controller and its parent HWND.
|
||||
This should be called any time a new, non-null HWND is set as the controller's parent,
|
||||
including when the controller is first created.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.UIElement_IsVisibleChanged(System.Object,System.Windows.DependencyPropertyChangedEventArgs)">
|
||||
<summary>
|
||||
This is a handler for our base UIElement's IsVisibleChanged event.
|
||||
It's predictably fired whenever IsVisible changes, and IsVisible reflects the actual current visibility status of the control.
|
||||
We just need to pass this info through to our CoreWebView2Controller so it can save some effort when the control isn't visible.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnWindowPositionChanged(System.Windows.Rect)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and called when our control's location has changed.
|
||||
The HwndHost takes care of updating the HWND we created.
|
||||
What we need to do is move our CoreWebView2 to match the new location.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.SourceProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.Source">
|
||||
<summary>
|
||||
The top-level <see cref="T:System.Uri"/> which the WebView is currently displaying (or will display once initialization of its <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> is finished).
|
||||
Generally speaking, getting this property is equivalent to getting the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.Source"/> property and setting this property (to a different value) is equivalent to calling the <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Navigate(System.String)"/> method.
|
||||
</summary>
|
||||
<remarks>
|
||||
Getting this property before the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> has been initialized will retrieve the last Uri which was set to it, or null (the default) if none has been.
|
||||
Setting this property before the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> has been initialized will cause initialization to start in the background (if not already in progress), after which the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> will navigate to the specified <see cref="T:System.Uri"/>.
|
||||
This property can never be set back to null or to a relative <see cref="T:System.Uri"/>.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</remarks>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<exception cref="T:System.NotImplementedException">Thrown if the property is set to <c>null</c>.</exception>
|
||||
<exception cref="T:System.ArgumentException">Thrown if the property is set to a relative <see cref="T:System.Uri"/> (i.e. a <see cref="T:System.Uri"/> whose <see cref="P:System.Uri.IsAbsoluteUri"/> property is <c>false</c>).</exception>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.SourcePropertyValid(System.Object)">
|
||||
<summary>
|
||||
This is a callback that WPF calls to validate a potential new Source value.
|
||||
</summary>
|
||||
<returns>
|
||||
True if the value is valid, false if it is not.
|
||||
If we return false then WPF should respond by throwing an <see cref="T:System.ArgumentException"/>.
|
||||
</returns>
|
||||
<remarks>
|
||||
Note that we unfortunately can't treat null as invalid here because null is valid prior to initialization.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.SourcePropertyChanged(System.Windows.DependencyObject,System.Windows.DependencyPropertyChangedEventArgs)">
|
||||
<summary>
|
||||
This is a callback that WPF calls when the WPF Source property's value changes.
|
||||
This might have been triggered by either:
|
||||
1) The caller set Source to programmatically trigger a navigation.
|
||||
2) The CoreWebView changed its own source and we're just updating the dependency property to match.
|
||||
We use <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.IsPropertyChangingFromCore(System.Windows.DependencyProperty)"/> to distinguish the two cases.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.SourceChanged">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_SourceChanged(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2SourceChangedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's SourceChanged event.
|
||||
Unsurprisingly, it fires when the CoreWebView2's source URI has been changed.
|
||||
Note that there are two distinct triggers for this:
|
||||
1) The CoreWebView2 was told to navigate programmatically (potentially by us, see SourcePropertyChanged).
|
||||
2) The user interacted with the CoreWebView2, e.g. clicked a link.
|
||||
In either of the above cases, this event might trigger several times due to e.g. redirection.
|
||||
Aside from propagating to our own event, we just need to update our WPF Source property to match the CoreWebView2's.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.NavigationStarting">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_NavigationStarting(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2NavigationStartingEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's NavigationStarting event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.NavigationCompleted">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_NavigationCompleted(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's NavigationCompleted event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_HistoryChanged(System.Object,System.Object)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's HistoryChanged event.
|
||||
We're handling it in order to update our WPF CanGoBack and CanGoForward properties.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.CanGoBackProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CanGoBack"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.CanGoBack">
|
||||
<summary>
|
||||
Returns <c>true</c> if the WebView can navigate to a previous page in the navigation history.
|
||||
Wrapper around the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/> property of <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
If <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> isn't initialized yet then returns <c>false</c>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.CanGoForwardProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CanGoForward"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.CanGoForward">
|
||||
<summary>
|
||||
Returns <c>true</c> if the WebView can navigate to a next page in the navigation history.
|
||||
Wrapper around the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoForward"/> property of <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
If <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> isn't initialized yet then returns <c>false</c>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoForward"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.TabIntoCore(System.Windows.Input.TraversalRequest)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and is called to inform us that tabbing has caused the focus to move into our control/window.
|
||||
Since WPF can't manage the transition of focus to a non-WPF HWND, it delegates the transition to us here.
|
||||
So our job is just to place the focus in our external HWND.
|
||||
</summary>
|
||||
<param name="request">Information about how the focus is moving.</param>
|
||||
<returns><c>true</c> to indicate that we handled the navigation, or <c>false</c> to indicate that we didn't.</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnGotKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.UIElement"/> and is called to inform us when we receive the keyboard focus.
|
||||
We handle this by passing the keyboard focus on to the underlying <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/>.
|
||||
We never want to land in a state where our window (this.Handle) actually has the keyboard focus.
|
||||
</summary>
|
||||
<param name="e">Arguments from the underlying GotKeyboardFocus event.</param>
|
||||
<remarks>
|
||||
Note that it's actually possible for us to receive keyboard focus without this method being called.
|
||||
One known case where that happens is when our parent window is deactivated while we have focus, then reactivated.
|
||||
We handle that case in <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.WndProc(System.IntPtr,System.Int32,System.IntPtr,System.IntPtr,System.Boolean@)"/>.
|
||||
</remarks>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Wpf.WebView2.WndProc(System.IntPtr,System.Int32,System.IntPtr,System.IntPtr,System.Boolean@)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_MoveFocusRequested(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2MoveFocusRequestedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's MoveFocusRequested event.
|
||||
It fires when the CoreWebView2Controller has focus but wants to move it elsewhere in the app.
|
||||
E.g. this happens when the user tabs past the last item in the CoreWebView2 and focus needs to return to some other app control.
|
||||
So our job is just to tell WPF to move the focus on to the next control.
|
||||
Note that we don't propagate this event outward as a standard WPF routed event because we've implemented its purpose here.
|
||||
If users of the control want to track focus shifting in/out of the control, they should use standard WPF events.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_GotFocus(System.Object,System.Object)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's GotFocus event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_LostFocus(System.Object,System.Object)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's LostFocus event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_AcceleratorKeyPressed(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2AcceleratorKeyPressedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's AcceleratorKeyPressed event.
|
||||
This is called to inform us about key presses that are likely to have special behavior (e.g. esc, return, Function keys, letters with modifier keys).
|
||||
WPF can't detect this input because Windows sends it directly to the Win32 CoreWebView2Controller control.
|
||||
We implement this by generating standard WPF key input events, allowing callers to handle the input in the usual WPF way if they want.
|
||||
If nobody handles the WPF key events then we'll allow the default CoreWebView2Controller logic (if any) to handle it.
|
||||
Of the possible options, this implementation should provide the most flexibility to callers.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyDown(System.Windows.Input.KeyEventArgs)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.UIElement"/> and called to allow us to handle key press input.
|
||||
WPF should never actually call this in response to keyboard events because we're hosting a non-WPF window.
|
||||
When our window has focus Windows will send the input directly to it rather than to WPF's top-level window and input system.
|
||||
This override should only be called when we're explicitly forwarding accelerator key input from the CoreWebView2 to WPF (in CoreWebView2Controller_AcceleratorKeyPressed).
|
||||
Even then, this KeyDownEvent is only triggered because our PreviewKeyDownEvent implementation explicitly triggers it, matching WPF's usual system.
|
||||
So the process is:
|
||||
<list type="number">
|
||||
<item><description>CoreWebView2Controller_AcceleratorKeyPressed</description></item>
|
||||
<item><description>PreviewKeyDownEvent</description></item>
|
||||
<item><description>KeyDownEvent</description></item>
|
||||
<item><description>OnKeyDown</description></item>
|
||||
</list>
|
||||
.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyUp(System.Windows.Input.KeyEventArgs)">
|
||||
<summary>
|
||||
See <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyDown(System.Windows.Input.KeyEventArgs)"/>.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnPreviewKeyDown(System.Windows.Input.KeyEventArgs)">
|
||||
<summary>
|
||||
This is the "Preview" (i.e. tunneling) version of <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyDown(System.Windows.Input.KeyEventArgs)"/>, so it actually happens first.
|
||||
Like OnKeyDown, this will only ever be called if we're explicitly forwarding key presses from the CoreWebView2.
|
||||
In order to mimic WPF's standard input handling, when we receive this we turn around and fire off the standard bubbling KeyDownEvent.
|
||||
That way others in the WPF tree see the same standard pair of input events that WPF itself would have triggered if it were handling the key press.
|
||||
</summary>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyDown(System.Windows.Input.KeyEventArgs)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnPreviewKeyUp(System.Windows.Input.KeyEventArgs)">
|
||||
<summary>
|
||||
See <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.OnPreviewKeyDown(System.Windows.Input.KeyEventArgs)"/>.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactorProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactor"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactor">
|
||||
<summary>
|
||||
The zoom factor for the WebView.
|
||||
This property directly exposes <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactor"/>, see its documentation for more info.
|
||||
Getting this property before the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> has been initialized will retrieve the last value which was set to it, or <c>1.0</c> (the default) if none has been.
|
||||
The most recent value set to this property before the CoreWebView2 has been initialized will be set on it after initialization.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactor"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactorPropertyChanged(System.Windows.DependencyObject,System.Windows.DependencyPropertyChangedEventArgs)">
|
||||
<summary>
|
||||
This is a callback that WPF calls when our WPF ZoomFactor property's value changes.
|
||||
This might have been triggered by either:
|
||||
1) The caller set ZoomFactor to change the zoom of the CoreWebView2.
|
||||
2) The CoreWebView2 changed its own ZoomFactor and we're just updating the dependency property to match.
|
||||
We use <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.IsPropertyChangingFromCore(System.Windows.DependencyProperty)"/> to distinguish the two cases.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactorChanged">
|
||||
<summary>
|
||||
The event is raised when the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactor"/> property changes.
|
||||
This event directly exposes <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactorChanged"/>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactor"/>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactorChanged"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_ZoomFactorChanged(System.Object,System.Object)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's ZoomFactorChanged event.
|
||||
Unsurprisingly, it fires when the CoreWebView2Controller's ZoomFactor has been changed.
|
||||
Note that there are two distinct triggers for this:
|
||||
1) The value was changed programmatically (potentially by us, see ZoomFactorPropertyChanged).
|
||||
2) The user interacted with the CoreWebView2, e.g. CTRL + Mouse Wheel.
|
||||
Aside from propagating to our own event, we just need to update our WPF ZoomFactor property to match the CoreWebView2Controller's.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.DefaultBackgroundColorProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.DefaultBackgroundColor"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.DefaultBackgroundColor">
|
||||
<summary>
|
||||
The default background color for the WebView.
|
||||
This property directly exposes <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2Controller.DefaultBackgroundColor"/>, see its documentation for more info.
|
||||
Getting this property before the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Controller"/> has been initialized will retrieve the last value which was
|
||||
set to it, or <c>Color.White</c> (the default) if none has been.
|
||||
The most recent value set to this property before CoreWebView2Controller has been initialized will be set on it after initialization.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.DefaultBackgroundColorPropertyChanged(System.Windows.DependencyObject,System.Windows.DependencyPropertyChangedEventArgs)">
|
||||
<summary>
|
||||
This is a callback that WPF calls when our WPF DefaultBackgroundColor property's value changes.
|
||||
Since CoreWebView2Controller does not update this property itself, this is only triggered by the
|
||||
caller setting DefaultBackgroundColor.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.DesignModeForegroundColorProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.DesignModeForegroundColor"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.DesignModeForegroundColor">
|
||||
<summary>
|
||||
The foreground color to be used in design mode.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.GoBack">
|
||||
<summary>
|
||||
Navigates the WebView to the previous page in the navigation history.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoBack"/>
|
||||
If <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> hasn't been initialized yet then does nothing.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.GoForward">
|
||||
<summary>
|
||||
Navigates the WebView to the next page in the navigation history.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoForward"/>.
|
||||
If <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> hasn't been initialized yet then does nothing.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoForward"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.Reload">
|
||||
<summary>
|
||||
Reloads the current page.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Reload"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> hasn't been initialized yet, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Reload"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.Stop">
|
||||
<summary>
|
||||
Stops all navigations and pending resource fetches.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Stop"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> hasn't been initialized yet, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Stop"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.NavigateToString(System.String)">
|
||||
<summary>
|
||||
Initiates a navigation to htmlContent as source HTML of a new document.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.NavigateToString(System.String)"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> hasn't been initialized yet, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<remarks>The <c>htmlContent</c> parameter may not be larger than 2 MB (2 * 1024 * 1024 bytes) in total size. The origin of the new page is <c>about:blank</c>.</remarks>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.NavigateToString(System.String)"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.ContentLoading">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_ContentLoading(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2ContentLoadingEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's ContentLoading event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.ExecuteScriptAsync(System.String)">
|
||||
<summary>
|
||||
Executes JavaScript code from the javaScript parameter in the current top level document rendered in the WebView.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.ExecuteScriptAsync(System.String)"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> hasn't been initialized yet, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.ExecuteScriptAsync(System.String)"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.WebMessageReceived">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_WebMessageReceived(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2WebMessageReceivedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's WebMessageReceived event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.IsInDesignMode">
|
||||
<summary>
|
||||
True when we're in design mode and shouldn't create an underlying CoreWebView2.
|
||||
</summary>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/netcoreapp3.0/Microsoft.Web.WebView2.Core.dll
vendored
Normal file
4456
packages/Microsoft.Web.WebView2.1.0.961.33/lib/netcoreapp3.0/Microsoft.Web.WebView2.Core.xml
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/netcoreapp3.0/Microsoft.Web.WebView2.WinForms.dll
vendored
Normal file
375
packages/Microsoft.Web.WebView2.1.0.961.33/lib/netcoreapp3.0/Microsoft.Web.WebView2.WinForms.xml
vendored
Normal file
@ -0,0 +1,375 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>Microsoft.Web.WebView2.WinForms</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties">
|
||||
<summary>
|
||||
This class is a bundle of the most common parameters used to create a <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/>.
|
||||
Its main purpose is to be set to <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CreationProperties"/> in order to customize the environment used by a <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/> during implicit initialization.
|
||||
</summary>
|
||||
<remarks>
|
||||
This class isn't intended to contain all possible environment customization options.
|
||||
If you need complete control over the environment used by a WebView2 control then you'll need to initialize the control explicitly by
|
||||
creating your own environment with <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> and passing it to <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/>
|
||||
*before* you set the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property to anything.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/> class documentation for an initialization overview.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.#ctor">
|
||||
<summary>
|
||||
Creates a new instance of <see cref="T:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties"/> with default data for all properties.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.BrowserExecutableFolder">
|
||||
<summary>
|
||||
Gets or sets the value to pass as the browserExecutableFolder parameter of <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.UserDataFolder">
|
||||
<summary>
|
||||
Gets or sets the value to pass as the userDataFolder parameter of <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.Language">
|
||||
<summary>
|
||||
Gets or sets the value to use for the Language property of the CoreWebView2EnvironmentOptions parameter passed to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.CoreWebView2CreationProperties.CreateEnvironmentAsync">
|
||||
<summary>
|
||||
Create a <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> using the current values of this instance's properties.
|
||||
</summary>
|
||||
<returns>A task which will provide the created environment on completion.</returns>
|
||||
<remarks>
|
||||
As long as no other properties on this instance are changed, repeated calls to this method will return the same task/environment as earlier calls.
|
||||
If some other property is changed then the next call to this method will return a different task/environment.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="T:Microsoft.Web.WebView2.WinForms.WebView2">
|
||||
<summary>
|
||||
Control to embed WebView2 in WinForms.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.#ctor">
|
||||
<summary>
|
||||
Create a new WebView2 WinForms control.
|
||||
After construction the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> property is <c>null</c>.
|
||||
Call <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> to initialize the underlying <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/>.
|
||||
</summary>
|
||||
<remarks>
|
||||
This control is effectively a wrapper around the WebView2 COM API, which you can find documentation for here: https://aka.ms/webview2
|
||||
You can directly access the underlying ICoreWebView2 interface and all of its functionality by accessing the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> property.
|
||||
Some of the most common COM functionality is also accessible directly through wrapper methods/properties/events on the control.
|
||||
|
||||
Upon creation, the control's CoreWebView2 property will be null.
|
||||
This is because creating the CoreWebView2 is an expensive operation which involves things like launching Edge browser processes.
|
||||
There are two ways to cause the CoreWebView2 to be created:
|
||||
1) Call the <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> method. This is referred to as explicit initialization.
|
||||
2) Set the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property. This is referred to as implicit initialization.
|
||||
Either option will start initialization in the background and return back to the caller without waiting for it to finish.
|
||||
To specify options regarding the initialization process, either pass your own <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> to EnsureCoreWebView2Async or set the control's <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CreationProperties"/> property prior to initialization.
|
||||
|
||||
When initialization has finished (regardless of how it was triggered) then the following things will occur, in this order:
|
||||
1) The control's <see cref="E:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2InitializationCompleted"/> event will be invoked. If you need to perform one time setup operations on the CoreWebView2 prior to its use then you should do so in a handler for that event.
|
||||
2) If a Uri has been set to the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property then the control will start navigating to it in the background (i.e. these steps will continue without waiting for the navigation to finish).
|
||||
3) The Task returned from <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> will complete.
|
||||
|
||||
For more details about any of the methods/properties/events involved in the initialization process, see its specific documentation.
|
||||
|
||||
Accelerator key presses (e.g. Ctrl+P) that occur within the control will
|
||||
fire standard key press events such as OnKeyDown. You can suppress the
|
||||
control's default implementation of an accelerator key press (e.g.
|
||||
printing, in the case of Ctrl+P) by setting the Handled property of its
|
||||
EventArgs to true. Also note that the underlying browser process is
|
||||
blocked while these handlers execute, so:
|
||||
<list type="number">
|
||||
<item>
|
||||
You should avoid doing a lot of work in these handlers.
|
||||
</item>
|
||||
<item>
|
||||
Some of the WebView2 and CoreWebView2 APIs may throw errors if
|
||||
invoked within these handlers due to being unable to communicate with
|
||||
the browser process.
|
||||
</item>
|
||||
</list>
|
||||
If you need to do a lot of work and/or invoke WebView2 APIs in response to
|
||||
accelerator keys then consider kicking off a background task or queuing
|
||||
the work for later execution on the UI thread.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.Dispose(System.Boolean)">
|
||||
<summary>
|
||||
Cleans up any resources being used.
|
||||
</summary>
|
||||
<param name="disposing"><c>true</c> if managed resources should be disposed; otherwise, <c>false</c>.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.OnPaint(System.Windows.Forms.PaintEventArgs)">
|
||||
<summary>
|
||||
Overrides the base OnPaint event to have custom actions
|
||||
in designer mode
|
||||
</summary>
|
||||
<param name="e">The graphics devices which is the source</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.WndProc(System.Windows.Forms.Message@)">
|
||||
<summary>
|
||||
Overrides the base WndProc events to handle specific window messages.
|
||||
</summary>
|
||||
<param name="m">The Message object containing the HWND window message and parameters</param>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CreationProperties">
|
||||
<summary>
|
||||
Gets or sets a bag of options which are used during initialization of the control's <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/>.
|
||||
This property cannot be modified (an exception will be thrown) after initialization of the control's CoreWebView2 has started.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown if initialization of the control's CoreWebView2 has already started.</exception>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)">
|
||||
<summary>
|
||||
Explicitly trigger initialization of the control's <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/>.
|
||||
</summary>
|
||||
<param name="environment">
|
||||
A pre-created <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> that should be used to create the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/>.
|
||||
Creating your own environment gives you control over several options that affect how the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is initialized.
|
||||
If you pass <c>null</c> (the default value) then a default environment will be created and used automatically.
|
||||
</param>
|
||||
<returns>
|
||||
A Task that represents the background initialization process.
|
||||
When the task completes then the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> property will be available for use (i.e. non-null).
|
||||
Note that the control's <see cref="E:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2InitializationCompleted"/> event will be invoked before the task completes
|
||||
or on exceptions.
|
||||
</returns>
|
||||
<remarks>
|
||||
Calling this method additional times will have no effect (any specified environment is ignored) and return the same Task as the first call.
|
||||
Calling this method after initialization has been implicitly triggered by setting the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property will have no effect (any specified environment is ignored) and simply return a Task representing that initialization already in progress.
|
||||
</remarks>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if this instance of <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is already disposed, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="P:System.Windows.Forms.Control.InvokeRequired"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.InitCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)">
|
||||
<summary>
|
||||
This is the private function which implements the actual background initialization task.
|
||||
Cannot be called if the control is already initialized or has been disposed.
|
||||
</summary>
|
||||
<param name="environment">
|
||||
The environment to use to create the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Controller"/>.
|
||||
If that is null then a default environment is created with <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> and its default parameters.
|
||||
</param>
|
||||
<returns>A task representing the background initialization process.</returns>
|
||||
<remarks>All the event handlers added here need to be removed in <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.Dispose(System.Boolean)"/>.</remarks>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CreateParams">
|
||||
<summary>
|
||||
Protected CreateParams property. Used to set custom window styles to the forms HWND.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.OnVisibleChanged(System.EventArgs)">
|
||||
<summary>
|
||||
Protected VisibilityChanged handler.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.OnSizeChanged(System.EventArgs)">
|
||||
<summary>
|
||||
Protected SizeChanged handler.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.Select(System.Boolean,System.Boolean)">
|
||||
<summary>
|
||||
Protected Select method: override this to capture tab direction when WebView control is activated
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.OnGotFocus(System.EventArgs)">
|
||||
<summary>
|
||||
Protected OnGotFocus handler.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.IsInitialized">
|
||||
<summary>
|
||||
True if initialization finished successfully and the control is not disposed yet.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.GetSitedParentSite(System.Windows.Forms.Control)">
|
||||
<summary>
|
||||
Recursive retrieval of the parent control
|
||||
</summary>
|
||||
<param name="control">The control to get the parent for</param>
|
||||
<returns>The root parent control</returns>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2">
|
||||
<summary>
|
||||
The underlying CoreWebView2. Use this property to perform more operations on the WebView2 content than is exposed
|
||||
on the WebView2. This value is null until it is initialized and the object itself has undefined behaviour once the control is disposed.
|
||||
You can force the underlying CoreWebView2 to
|
||||
initialize via the <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> method.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="P:System.Windows.Forms.Control.InvokeRequired"/> for more info.</exception>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.ZoomFactor">
|
||||
<summary>
|
||||
The zoom factor for the WebView.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.Source">
|
||||
<summary>
|
||||
The Source property is the URI of the top level document of the
|
||||
WebView2. Setting the Source is equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Navigate(System.String)"/>.
|
||||
Setting the Source will trigger initialization of the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/>, if not already initialized.
|
||||
The default value of Source is <c>null</c>, indicating that the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized.
|
||||
</summary>
|
||||
<exception cref="T:System.ArgumentException">Specified value is not an absolute <see cref="T:System.Uri"/>.</exception>
|
||||
<exception cref="T:System.NotImplementedException">Specified value is <c>null</c> and the control is initialized.</exception>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Navigate(System.String)"/>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CanGoForward">
|
||||
<summary>
|
||||
Returns true if the webview can navigate to a next page in the
|
||||
navigation history via the <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.GoForward"/> method.
|
||||
This is equivalent to the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoForward"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this property is <c>false</c>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoForward"/>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.CanGoBack">
|
||||
<summary>
|
||||
Returns <c>true</c> if the webview can navigate to a previous page in the
|
||||
navigation history via the <see cref="M:Microsoft.Web.WebView2.WinForms.WebView2.GoBack"/> method.
|
||||
This is equivalent to the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this property is <c>false</c>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.WinForms.WebView2.DefaultBackgroundColor">
|
||||
<summary>
|
||||
The default background color for the WebView.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.ExecuteScriptAsync(System.String)">
|
||||
<summary>
|
||||
Executes the provided script in the top level document of the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.ExecuteScriptAsync(System.String)"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">The underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized.</exception>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown when browser process has unexpectedly and left this control in an invalid state. We are considering throwing a different type of exception for this case in the future.</exception>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.ExecuteScriptAsync(System.String)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.Reload">
|
||||
<summary>
|
||||
Reloads the top level document of the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Reload"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">The underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized.</exception>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown when browser process has unexpectedly and left this control in an invalid state. We are considering throwing a different type of exception for this case in the future.</exception>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Reload"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.GoForward">
|
||||
<summary>
|
||||
Navigates to the next page in navigation history.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoForward"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this method does nothing.
|
||||
</summary>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoForward"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.GoBack">
|
||||
<summary>
|
||||
Navigates to the previous page in navigation history.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoBack"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this method does nothing.
|
||||
</summary>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoBack"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.NavigateToString(System.String)">
|
||||
<summary>
|
||||
Renders the provided HTML as the top level document of the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.NavigateToString(System.String)"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">The underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized.</exception>
|
||||
<exception cref="T:System.InvalidOperationException">Thrown when browser process has unexpectedly and left this control in an invalid state. We are considering throwing a different type of exception for this case in the future.</exception>
|
||||
<remarks>The <c>htmlContent</c> parameter may not be larger than 2 MB (2 * 1024 * 1024 bytes) in total size. The origin of the new page is <c>about:blank</c>.</remarks>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.NavigateToString(System.String)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.Stop">
|
||||
<summary>
|
||||
Stops any in progress navigation in the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Stop"/>.
|
||||
If the underlying <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> is not yet initialized, this method does nothing.
|
||||
</summary>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Stop"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2InitializationCompleted">
|
||||
<summary>
|
||||
This event is triggered either 1) when the control's <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.CoreWebView2"/> has finished being initialized (regardless of how it was triggered or whether it succeeded) but before it is used for anything
|
||||
OR 2) the initialization failed.
|
||||
You should handle this event if you need to perform one time setup operations on the CoreWebView2 which you want to affect all of its usages
|
||||
(e.g. adding event handlers, configuring settings, installing document creation scripts, adding host objects).
|
||||
</summary>
|
||||
<remarks>
|
||||
This sender will be the WebView2 control, whose CoreWebView2 property will now be valid (i.e. non-null) for the first time
|
||||
if <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs.IsSuccess"/> is true.
|
||||
Unlikely this event can fire second time (after reporting initialization success first)
|
||||
if the initialization is followed by navigation which fails.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.NavigationStarting">
|
||||
<summary>
|
||||
NavigationStarting dispatches before a new navigate starts for the top
|
||||
level document of the <see cref="T:Microsoft.Web.WebView2.WinForms.WebView2"/>.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.NavigationCompleted">
|
||||
<summary>
|
||||
NavigationCompleted dispatches after a navigate of the top level
|
||||
document completes rendering either successfully or not.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.WebMessageReceived">
|
||||
<summary>
|
||||
WebMessageReceived dispatches after web content sends a message to the
|
||||
app host via <c>chrome.webview.postMessage</c>.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.SourceChanged">
|
||||
<summary>
|
||||
SourceChanged dispatches after the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.Source"/> property changes. This may happen
|
||||
during a navigation or if otherwise the script in the page changes the
|
||||
URI of the document.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.ContentLoading">
|
||||
<summary>
|
||||
ContentLoading dispatches after a navigation begins to a new URI and the
|
||||
content of that URI begins to render.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.WinForms.WebView2.ZoomFactorChanged">
|
||||
<summary>
|
||||
ZoomFactorChanged dispatches when the <see cref="P:Microsoft.Web.WebView2.WinForms.WebView2.ZoomFactor"/> property changes.
|
||||
This is equivalent to the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactorChanged"/> event.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactorChanged"/>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.WinForms.WebView2.components">
|
||||
<summary>
|
||||
Required designer variable.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.WinForms.WebView2.InitializeComponent">
|
||||
<summary>
|
||||
Required method for Designer support - do not modify
|
||||
the contents of this method with the code editor.
|
||||
</summary>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/lib/netcoreapp3.0/Microsoft.Web.WebView2.Wpf.dll
vendored
Normal file
800
packages/Microsoft.Web.WebView2.1.0.961.33/lib/netcoreapp3.0/Microsoft.Web.WebView2.Wpf.xml
vendored
Normal file
@ -0,0 +1,800 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>Microsoft.Web.WebView2.Wpf</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties">
|
||||
<summary>
|
||||
This class is a bundle of the most common parameters used to create a <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/>.
|
||||
Its main purpose is to be set to <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> in order to customize the environment used by a <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> during implicit initialization.
|
||||
It is also a nice WPF integration utility which allows commonly used environment parameters to be dependency properties and be created and used in markup.
|
||||
</summary>
|
||||
<remarks>
|
||||
This class isn't intended to contain all possible environment customization options.
|
||||
If you need complete control over the environment used by a WebView2 control then you'll need to initialize the control explicitly by
|
||||
creating your own environment with <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> and passing it to <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/>
|
||||
*before* you set the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property to anything.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.#ctor">
|
||||
<summary>
|
||||
Creates a new instance of <see cref="T:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties"/> with default data for all properties.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.BrowserExecutableFolderProperty">
|
||||
<summary>
|
||||
The WPF DependencyProperty which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.BrowserExecutableFolder"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.BrowserExecutableFolder">
|
||||
<summary>
|
||||
Gets or sets the value to pass as the browserExecutableFolder parameter of <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.UserDataFolderProperty">
|
||||
<summary>
|
||||
The WPF DependencyProperty which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.UserDataFolder"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.UserDataFolder">
|
||||
<summary>
|
||||
Gets or sets the value to pass as the userDataFolder parameter of <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.LanguageProperty">
|
||||
<summary>
|
||||
The WPF DependencyProperty which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.Language"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.Language">
|
||||
<summary>
|
||||
Gets or sets the value to use for the Language property of the CoreWebView2EnvironmentOptions parameter passed to <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(System.String,System.String,Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions)"/> when creating an environment with this instance.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties.CreateEnvironmentAsync">
|
||||
<summary>
|
||||
Create a <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> using the current values of this instance's properties.
|
||||
</summary>
|
||||
<returns>A task which will provide the created environment on completion.</returns>
|
||||
<remarks>
|
||||
As long as no other properties on this instance are changed, repeated calls to this method will return the same task/environment as earlier calls.
|
||||
If some other property is changed then the next call to this method will return a different task/environment.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="T:Microsoft.Web.WebView2.Wpf.WebView2">
|
||||
<summary>
|
||||
A control to embed web content in a WPF application.
|
||||
</summary>
|
||||
<remarks>
|
||||
This control is effectively a wrapper around the [WebView2 COM
|
||||
API](https://aka.ms/webview2). You can directly access the underlying
|
||||
ICoreWebView2 interface and all of its functionality by accessing the
|
||||
<see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> property. Some of the most common COM
|
||||
functionality is also accessible directly through wrapper
|
||||
methods/properties/events on the control.
|
||||
|
||||
Upon creation, the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> property will be
|
||||
<c>null</c>. This is because creating the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> is an
|
||||
expensive operation which involves things like launching Edge browser
|
||||
processes. There are two ways to cause the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> to
|
||||
be created:
|
||||
<list type="bullet">
|
||||
<item><description>
|
||||
Call the <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> method. This is
|
||||
referred to as explicit initialization.
|
||||
</description></item>
|
||||
<item><description>
|
||||
Set the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property (which could be done from
|
||||
markup, for example). This is referred to as implicit initialization.
|
||||
Either option will start initialization in the background and return
|
||||
back to the caller without waiting for it to finish.
|
||||
To specify options regarding the initialization process, either pass
|
||||
your own <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> to <see
|
||||
cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> or set the control's <see
|
||||
cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> property prior to initialization.
|
||||
</description></item>
|
||||
</list>
|
||||
|
||||
When initialization has finished (regardless of how it was triggered or
|
||||
whether it succeeded) then the following things will occur, in this
|
||||
order:
|
||||
<list type="number">
|
||||
<item><description>
|
||||
The control's <see cref="E:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2InitializationCompleted"/> event
|
||||
will be invoked. If you need to perform one time setup operations on
|
||||
the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> prior to its use then you should
|
||||
do so in a handler for that event.
|
||||
</description></item>
|
||||
<item><description>
|
||||
If initialization was successful and a Uri has been set to the <see
|
||||
cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property then the control will start navigating to it in
|
||||
the background (i.e. these steps will continue without waiting for the
|
||||
navigation to finish).
|
||||
</description></item>
|
||||
<item><description>
|
||||
The Task returned from <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/> will
|
||||
complete.
|
||||
</description></item>
|
||||
</list>
|
||||
|
||||
For more details about any of the methods/properties/events involved in
|
||||
the initialization process, see its specific documentation.
|
||||
|
||||
Because the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> is a very heavyweight
|
||||
object (potentially responsible for multiple running processes and
|
||||
megabytes of disk space) the control implements <see
|
||||
cref="T:System.IDisposable"/> to provide an explicit means to free it.
|
||||
Calling <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> will release the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>
|
||||
and its underlying resources (except any that are also being used by other
|
||||
WebViews), and reset <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> to <c>null</c>. After <see
|
||||
cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has been called the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> cannot be
|
||||
re-initialized, and any attempt to use functionality which requires it
|
||||
will throw an <see cref="T:System.ObjectDisposedException"/>.
|
||||
|
||||
Accelerator key presses (e.g. Ctrl+P) that occur within the control will
|
||||
fire standard key press events such as OnKeyDown. You can suppress the
|
||||
control's default implementation of an accelerator key press (e.g.
|
||||
printing, in the case of Ctrl+P) by setting the Handled property of its
|
||||
EventArgs to true. Also note that the underlying browser process is
|
||||
blocked while these handlers execute, so:
|
||||
<list type="number">
|
||||
<item>
|
||||
<description>You should avoid doing a lot of work in these handlers.</description>
|
||||
</item>
|
||||
<item><description>
|
||||
Some of the WebView2 and CoreWebView2 APIs may throw errors if
|
||||
invoked within these handlers due to being unable to communicate with
|
||||
the browser process.
|
||||
</description></item>
|
||||
</list>
|
||||
If you need to do a lot of work and/or invoke WebView2 APIs in response to
|
||||
accelerator keys then consider kicking off a background task or queuing
|
||||
the work for later execution on the UI thread.
|
||||
|
||||
Note that this control extends <see cref="T:System.Windows.Interop.HwndHost"/> in order to embed
|
||||
windows which live outside of the WPF ecosystem. This has some
|
||||
implications regarding the control's input and output behavior as well as
|
||||
the functionality it "inherits" from <see cref="T:System.Windows.UIElement"/> and <see
|
||||
cref="T:System.Windows.FrameworkElement"/>.
|
||||
See the <see cref="T:System.Windows.Interop.HwndHost"/> and [WPF/Win32
|
||||
interop](https://docs.microsoft.com/dotnet/framework/wpf/advanced/wpf-and-win32-interoperation#hwnds-inside-wpf)
|
||||
documentation for more information.
|
||||
</remarks>
|
||||
<seealso cref="T:System.Windows.Interop.HwndHost"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.#ctor">
|
||||
<summary>
|
||||
Creates a new instance of a WebView2 control.
|
||||
Note that the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> will be null until initialized.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.CreationPropertiesProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> property.
|
||||
</summary>
|
||||
<seealso cref="T:System.Windows.DependencyProperty"/>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties">
|
||||
<summary>
|
||||
Gets or sets a bag of options which are used during initialization of the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
Setting this property will not work after initialization of the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> has started (the old value will be retained).
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.BuildWindowCore(System.Runtime.InteropServices.HandleRef)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and is called to instruct us to create our HWND.
|
||||
</summary>
|
||||
<param name="hwndParent">The HWND that we should use as the parent of the one we create.</param>
|
||||
<returns>The HWND that we created.</returns>
|
||||
<seealso cref="M:System.Windows.Interop.HwndHost.BuildWindowCore(System.Runtime.InteropServices.HandleRef)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.DestroyWindowCore(System.Runtime.InteropServices.HandleRef)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and is called to instruct us to destroy our HWND.
|
||||
</summary>
|
||||
<param name="hwnd">Our HWND that we need to destroy.</param>
|
||||
<seealso cref="M:System.Windows.Interop.HwndHost.DestroyWindowCore(System.Runtime.InteropServices.HandleRef)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.WndProc(System.IntPtr,System.Int32,System.IntPtr,System.IntPtr,System.Boolean@)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and is called to provide us with Win32 messages that are sent to our hwnd.
|
||||
</summary>
|
||||
<param name="hwnd">Window receiving the message (should always match our <see cref="P:System.Windows.Interop.HwndHost.Handle"/>).</param>
|
||||
<param name="msg">Indicates the message being received. See Win32 documentation for WM_* constant values.</param>
|
||||
<param name="wParam">The "wParam" data being provided with the message. Meaning varies by message.</param>
|
||||
<param name="lParam">The "lParam" data being provided with the message. Meaning varies by message.</param>
|
||||
<param name="handled">If true then the message will not be forwarded to any (more) <see cref="E:System.Windows.Interop.HwndHost.MessageHook"/> handlers.</param>
|
||||
<returns>Return value varies by message.</returns>
|
||||
<seealso cref="M:System.Windows.Interop.HwndHost.WndProc(System.IntPtr,System.Int32,System.IntPtr,System.IntPtr,System.Boolean@)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnRender(System.Windows.Media.DrawingContext)">
|
||||
<summary>
|
||||
Override for painting to draw
|
||||
</summary>
|
||||
<param name="dc">The tools to handle the drawing via <see cref="T:System.Windows.Media.DrawingContext"/>.</param>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2">
|
||||
<summary>
|
||||
Accesses the complete functionality of the underlying <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> COM API.
|
||||
Returns <c>null</c> until initialization has completed.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2InitializationCompleted">
|
||||
<summary>
|
||||
This event is triggered either
|
||||
1) when the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> has finished being initialized (regardless of how initialization was triggered) but before it is used for anything, or
|
||||
2) if the initialization failed.
|
||||
You should handle this event if you need to perform one time setup operations on the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> which you want to affect all of its usages.
|
||||
(e.g. adding event handlers, configuring settings, installing document creation scripts, adding host objects).
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
<remarks>
|
||||
This sender will be the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whose <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> property will now be valid (i.e. non-null) for the first time
|
||||
if <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs.IsSuccess"/> is <c>true</c>.
|
||||
Unlikely this event can fire second time (after reporting initialization success first)
|
||||
if the initialization is followed by navigation which fails.
|
||||
</remarks>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)">
|
||||
<summary>
|
||||
Explicitly triggers initialization of the control's <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</summary>
|
||||
<param name="environment">
|
||||
A pre-created <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Environment"/> that should be used to create the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/>.
|
||||
Creating your own environment gives you control over several options that affect how the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> is initialized.
|
||||
If you pass an environment to this method then it will override any settings specified on the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> property.
|
||||
If you pass <c>null</c> (the default value) and no value has been set to <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> then a default environment will be created and used automatically.
|
||||
</param>
|
||||
<returns>
|
||||
A Task that represents the background initialization process.
|
||||
When the task completes then the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> property will be available for use (i.e. non-null).
|
||||
Note that the control's <see cref="E:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2InitializationCompleted"/> event will be invoked before the task completes.
|
||||
</returns>
|
||||
<remarks>
|
||||
Calling this method additional times will have no effect (any specified environment is ignored) and return the same Task as the first call.
|
||||
Calling this method after initialization has been implicitly triggered by setting the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property will have no effect (any specified environment is ignored) and simply return a Task representing that initialization already in progress.
|
||||
Note that even though this method is asynchronous and returns a Task, it still must be called on the UI thread like most public functionality of most UI controls.
|
||||
</remarks>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)">
|
||||
<summary>
|
||||
This is called by our base class according to the typical implementation of the <see cref="T:System.IDisposable"/> pattern.
|
||||
We implement it by releasing all of our underlying COM resources, including our <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
</summary>
|
||||
<param name="disposing">True if a caller is explicitly calling Dispose, false if we're being finalized.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_ProcessFailed(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2ProcessFailedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's ProcessFailedEvent
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.BeginInit">
|
||||
<summary>
|
||||
Implementation of the ISupportInitialize pattern.
|
||||
Prevents the control from implicitly initializing its <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> until <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EndInit"/> is called.
|
||||
Does *not* prevent explicit initialization of the CoreWebView2 (i.e. <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.EnsureCoreWebView2Async(Microsoft.Web.WebView2.Core.CoreWebView2Environment)"/>).
|
||||
Mainly intended for use by interactive UI designers.
|
||||
</summary>
|
||||
<remarks>
|
||||
Note that the "Initialize" in ISupportInitialize and the "Init" in BeginInit/EndInit mean
|
||||
something different and more general than this control's specific concept of initializing
|
||||
its CoreWebView2 (explicitly or implicitly). This ISupportInitialize pattern is a general
|
||||
way to set batches of properties on the control to their initial values without triggering
|
||||
any dependent side effects until all of the values are set (i.e. until EndInit is called).
|
||||
In the case of this control, a specific side effect to be avoided is triggering implicit
|
||||
initialization of the CoreWebView2 when setting the Source property.
|
||||
For example, normally if you set <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CreationProperties"/> after you've already set Source,
|
||||
the data set to CreationProperties is ignored because implicit initialization has already started.
|
||||
However, if you set the two properties (in the same order) in between calls to BeginInit and
|
||||
EndInit then the implicit initialization of the CoreWebView2 is delayed until EndInit, so the data
|
||||
set to CreationProperties is still used even though it was set after Source.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.EndInit">
|
||||
<summary>
|
||||
Implementation of the ISupportInitialize pattern.
|
||||
Invokes any functionality that has been delayed since the corresponding call to <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.BeginInit"/>.
|
||||
Mainly intended for use by interactive UI designers.
|
||||
</summary>
|
||||
<remarks>
|
||||
See the documentation of <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.BeginInit"/> for more information.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.WhenInit_Source(System.Action)">
|
||||
<summary>
|
||||
Specifies a Source-related action to be invoked but which must be delayed if BeginInit has already been called but EndInit hasn't.
|
||||
If the control is currently between BeginInit/EndInit calls then the action will be invoked during EndInit.
|
||||
Otherwise the action will be invoked immediately.
|
||||
If this is called multiple times between BeginInit/EndInit then the action passed to the last call is the only one that will be invoked during EndInit.
|
||||
</summary>
|
||||
<param name="action">The Source-related action to invoke, delayed until EndInit if necessary.</param>
|
||||
<remarks>
|
||||
In the future if we need this delayed-invoke functionality for actions unrelated to Source,
|
||||
then we should generalize _initAction_Source to a list and generalize this method to take a list index along with the action.
|
||||
Then we can just assign each index to a different potential action (e.g. 0 for Source), and potentially use constants to name the indices.
|
||||
For now it didn't seem worth dynamically allocating a list for one thing,
|
||||
but I still wanted to keep the delay-or-not logic abstracted away from the Source setter.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.SetCurrentValueFromCore(System.Windows.DependencyProperty,System.Object)">
|
||||
<summary>
|
||||
Updates one of our dependency properties to match a new value from the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
It both sets the value and remembers (in _propertyChangingFromCore) that it came from the CoreWebView2 rather than the caller,
|
||||
allowing the property's "on changed" handler to alter its behavior based on where the new value came from.
|
||||
It's only intended to be called in a CoreWebView2 event handler that's informing us of a new property value.
|
||||
It's basically just a wrapper around the inherited SetCurrentValue which also maintains _propertyChangingFromCore.
|
||||
See the comments on <see cref="F:Microsoft.Web.WebView2.Wpf.WebView2._propertyChangingFromCore"/> for additional background info.
|
||||
One more thing worth explicitly stating is that it wraps SetCurrentValue rather than SetValue,
|
||||
in order to avoid overwriting any OneWay bindings that are set on the specified properties.
|
||||
Check the link https://stackoverflow.com/q/4230698 for more information about the difference between SetValue and SetCurrentValue.
|
||||
</summary>
|
||||
<param name="property">The property to change due to an equivalent change in the CoreWebView2.</param>
|
||||
<param name="value">The new value from the CoreWebView2.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.IsPropertyChangingFromCore(System.Windows.DependencyProperty)">
|
||||
<summary>
|
||||
Checks if a given property is currently being updated to match an equivalent change in the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
This method should only be called from a property's "on changed" handler; it has no meaning at any other time.
|
||||
It is used to determine if the property is changing to match the CoreWebView2 or because the caller set it.
|
||||
Usually this is used in order to decide if the new value needs to be propagated down to the CoreWebView2.
|
||||
See the comments on <see cref="F:Microsoft.Web.WebView2.Wpf.WebView2._propertyChangingFromCore"/> for additional background info.
|
||||
</summary>
|
||||
<param name="property">The property to check.</param>
|
||||
<returns>True if the property is changing to match the CoreWebView2, or false if the property was changed by the caller.</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.ReparentController(System.IntPtr,System.Boolean)">
|
||||
<summary>
|
||||
Changes our controller's ParentWindow to the given HWND, along with any other necessary associated work.
|
||||
</summary>
|
||||
<param name="hwnd">The new HWND to set as the controller's parent. IntPtr.Zero means that the controller will have no parent and the CoreWebView2 will be hidden.</param>
|
||||
<param name="sync">Whether or not to call <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.SyncControllerWithParentWindow"/> as required. Defaults to true. If you pass false then you should call it yourself if required.</param>
|
||||
<remarks>
|
||||
Reparenting the controller isn't necessarily as simple as changing its ParentWindow property,
|
||||
and this method exists to ensure that any other work that needs to be done at the same time gets done.
|
||||
The reason that SyncControllerWithParentWindow isn't baked directly into this method is because
|
||||
sometimes we want to call the Sync functionality without necessarily reparenting (e.g. during initialization).
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.SyncControllerWithParentWindow">
|
||||
<summary>
|
||||
Syncs visual/windowing information between the controller and its parent HWND.
|
||||
This should be called any time a new, non-null HWND is set as the controller's parent,
|
||||
including when the controller is first created.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.UIElement_IsVisibleChanged(System.Object,System.Windows.DependencyPropertyChangedEventArgs)">
|
||||
<summary>
|
||||
This is a handler for our base UIElement's IsVisibleChanged event.
|
||||
It's predictably fired whenever IsVisible changes, and IsVisible reflects the actual current visibility status of the control.
|
||||
We just need to pass this info through to our CoreWebView2Controller so it can save some effort when the control isn't visible.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnWindowPositionChanged(System.Windows.Rect)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and called when our control's location has changed.
|
||||
The HwndHost takes care of updating the HWND we created.
|
||||
What we need to do is move our CoreWebView2 to match the new location.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.SourceProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.Source"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.Source">
|
||||
<summary>
|
||||
The top-level <see cref="T:System.Uri"/> which the WebView is currently displaying (or will display once initialization of its <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> is finished).
|
||||
Generally speaking, getting this property is equivalent to getting the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.Source"/> property and setting this property (to a different value) is equivalent to calling the <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Navigate(System.String)"/> method.
|
||||
</summary>
|
||||
<remarks>
|
||||
Getting this property before the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> has been initialized will retrieve the last Uri which was set to it, or null (the default) if none has been.
|
||||
Setting this property before the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> has been initialized will cause initialization to start in the background (if not already in progress), after which the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> will navigate to the specified <see cref="T:System.Uri"/>.
|
||||
This property can never be set back to null or to a relative <see cref="T:System.Uri"/>.
|
||||
See the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> class documentation for an initialization overview.
|
||||
</remarks>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<exception cref="T:System.NotImplementedException">Thrown if the property is set to <c>null</c>.</exception>
|
||||
<exception cref="T:System.ArgumentException">Thrown if the property is set to a relative <see cref="T:System.Uri"/> (i.e. a <see cref="T:System.Uri"/> whose <see cref="P:System.Uri.IsAbsoluteUri"/> property is <c>false</c>).</exception>
|
||||
<seealso cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.SourcePropertyValid(System.Object)">
|
||||
<summary>
|
||||
This is a callback that WPF calls to validate a potential new Source value.
|
||||
</summary>
|
||||
<returns>
|
||||
True if the value is valid, false if it is not.
|
||||
If we return false then WPF should respond by throwing an <see cref="T:System.ArgumentException"/>.
|
||||
</returns>
|
||||
<remarks>
|
||||
Note that we unfortunately can't treat null as invalid here because null is valid prior to initialization.
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.SourcePropertyChanged(System.Windows.DependencyObject,System.Windows.DependencyPropertyChangedEventArgs)">
|
||||
<summary>
|
||||
This is a callback that WPF calls when the WPF Source property's value changes.
|
||||
This might have been triggered by either:
|
||||
1) The caller set Source to programmatically trigger a navigation.
|
||||
2) The CoreWebView changed its own source and we're just updating the dependency property to match.
|
||||
We use <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.IsPropertyChangingFromCore(System.Windows.DependencyProperty)"/> to distinguish the two cases.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.SourceChanged">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.SourceChanged"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_SourceChanged(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2SourceChangedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's SourceChanged event.
|
||||
Unsurprisingly, it fires when the CoreWebView2's source URI has been changed.
|
||||
Note that there are two distinct triggers for this:
|
||||
1) The CoreWebView2 was told to navigate programmatically (potentially by us, see SourcePropertyChanged).
|
||||
2) The user interacted with the CoreWebView2, e.g. clicked a link.
|
||||
In either of the above cases, this event might trigger several times due to e.g. redirection.
|
||||
Aside from propagating to our own event, we just need to update our WPF Source property to match the CoreWebView2's.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.NavigationStarting">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationStarting"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_NavigationStarting(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2NavigationStartingEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's NavigationStarting event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.NavigationCompleted">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.NavigationCompleted"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_NavigationCompleted(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's NavigationCompleted event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_HistoryChanged(System.Object,System.Object)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's HistoryChanged event.
|
||||
We're handling it in order to update our WPF CanGoBack and CanGoForward properties.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.CanGoBackProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CanGoBack"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.CanGoBack">
|
||||
<summary>
|
||||
Returns <c>true</c> if the WebView can navigate to a previous page in the navigation history.
|
||||
Wrapper around the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/> property of <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
If <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> isn't initialized yet then returns <c>false</c>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.CanGoForwardProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CanGoForward"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.CanGoForward">
|
||||
<summary>
|
||||
Returns <c>true</c> if the WebView can navigate to a next page in the navigation history.
|
||||
Wrapper around the <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoForward"/> property of <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/>.
|
||||
If <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> isn't initialized yet then returns <c>false</c>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoForward"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.TabIntoCore(System.Windows.Input.TraversalRequest)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.Interop.HwndHost"/> and is called to inform us that tabbing has caused the focus to move into our control/window.
|
||||
Since WPF can't manage the transition of focus to a non-WPF HWND, it delegates the transition to us here.
|
||||
So our job is just to place the focus in our external HWND.
|
||||
</summary>
|
||||
<param name="request">Information about how the focus is moving.</param>
|
||||
<returns><c>true</c> to indicate that we handled the navigation, or <c>false</c> to indicate that we didn't.</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnGotKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.UIElement"/> and is called to inform us when we receive the keyboard focus.
|
||||
We handle this by passing the keyboard focus on to the underlying <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/>.
|
||||
We never want to land in a state where our window (this.Handle) actually has the keyboard focus.
|
||||
</summary>
|
||||
<param name="e">Arguments from the underlying GotKeyboardFocus event.</param>
|
||||
<remarks>
|
||||
Note that it's actually possible for us to receive keyboard focus without this method being called.
|
||||
One known case where that happens is when our parent window is deactivated while we have focus, then reactivated.
|
||||
We handle that case in <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.WndProc(System.IntPtr,System.Int32,System.IntPtr,System.IntPtr,System.Boolean@)"/>.
|
||||
</remarks>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Wpf.WebView2.WndProc(System.IntPtr,System.Int32,System.IntPtr,System.IntPtr,System.Boolean@)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_MoveFocusRequested(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2MoveFocusRequestedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's MoveFocusRequested event.
|
||||
It fires when the CoreWebView2Controller has focus but wants to move it elsewhere in the app.
|
||||
E.g. this happens when the user tabs past the last item in the CoreWebView2 and focus needs to return to some other app control.
|
||||
So our job is just to tell WPF to move the focus on to the next control.
|
||||
Note that we don't propagate this event outward as a standard WPF routed event because we've implemented its purpose here.
|
||||
If users of the control want to track focus shifting in/out of the control, they should use standard WPF events.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_GotFocus(System.Object,System.Object)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's GotFocus event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_LostFocus(System.Object,System.Object)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's LostFocus event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_AcceleratorKeyPressed(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2AcceleratorKeyPressedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's AcceleratorKeyPressed event.
|
||||
This is called to inform us about key presses that are likely to have special behavior (e.g. esc, return, Function keys, letters with modifier keys).
|
||||
WPF can't detect this input because Windows sends it directly to the Win32 CoreWebView2Controller control.
|
||||
We implement this by generating standard WPF key input events, allowing callers to handle the input in the usual WPF way if they want.
|
||||
If nobody handles the WPF key events then we'll allow the default CoreWebView2Controller logic (if any) to handle it.
|
||||
Of the possible options, this implementation should provide the most flexibility to callers.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyDown(System.Windows.Input.KeyEventArgs)">
|
||||
<summary>
|
||||
This is overridden from <see cref="T:System.Windows.UIElement"/> and called to allow us to handle key press input.
|
||||
WPF should never actually call this in response to keyboard events because we're hosting a non-WPF window.
|
||||
When our window has focus Windows will send the input directly to it rather than to WPF's top-level window and input system.
|
||||
This override should only be called when we're explicitly forwarding accelerator key input from the CoreWebView2 to WPF (in CoreWebView2Controller_AcceleratorKeyPressed).
|
||||
Even then, this KeyDownEvent is only triggered because our PreviewKeyDownEvent implementation explicitly triggers it, matching WPF's usual system.
|
||||
So the process is:
|
||||
<list type="number">
|
||||
<item><description>CoreWebView2Controller_AcceleratorKeyPressed</description></item>
|
||||
<item><description>PreviewKeyDownEvent</description></item>
|
||||
<item><description>KeyDownEvent</description></item>
|
||||
<item><description>OnKeyDown</description></item>
|
||||
</list>
|
||||
.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyUp(System.Windows.Input.KeyEventArgs)">
|
||||
<summary>
|
||||
See <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyDown(System.Windows.Input.KeyEventArgs)"/>.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnPreviewKeyDown(System.Windows.Input.KeyEventArgs)">
|
||||
<summary>
|
||||
This is the "Preview" (i.e. tunneling) version of <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyDown(System.Windows.Input.KeyEventArgs)"/>, so it actually happens first.
|
||||
Like OnKeyDown, this will only ever be called if we're explicitly forwarding key presses from the CoreWebView2.
|
||||
In order to mimic WPF's standard input handling, when we receive this we turn around and fire off the standard bubbling KeyDownEvent.
|
||||
That way others in the WPF tree see the same standard pair of input events that WPF itself would have triggered if it were handling the key press.
|
||||
</summary>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Wpf.WebView2.OnKeyDown(System.Windows.Input.KeyEventArgs)"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.OnPreviewKeyUp(System.Windows.Input.KeyEventArgs)">
|
||||
<summary>
|
||||
See <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.OnPreviewKeyDown(System.Windows.Input.KeyEventArgs)"/>.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactorProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactor"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactor">
|
||||
<summary>
|
||||
The zoom factor for the WebView.
|
||||
This property directly exposes <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactor"/>, see its documentation for more info.
|
||||
Getting this property before the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> has been initialized will retrieve the last value which was set to it, or <c>1.0</c> (the default) if none has been.
|
||||
The most recent value set to this property before the CoreWebView2 has been initialized will be set on it after initialization.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactor"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactorPropertyChanged(System.Windows.DependencyObject,System.Windows.DependencyPropertyChangedEventArgs)">
|
||||
<summary>
|
||||
This is a callback that WPF calls when our WPF ZoomFactor property's value changes.
|
||||
This might have been triggered by either:
|
||||
1) The caller set ZoomFactor to change the zoom of the CoreWebView2.
|
||||
2) The CoreWebView2 changed its own ZoomFactor and we're just updating the dependency property to match.
|
||||
We use <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.IsPropertyChangingFromCore(System.Windows.DependencyProperty)"/> to distinguish the two cases.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactorChanged">
|
||||
<summary>
|
||||
The event is raised when the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactor"/> property changes.
|
||||
This event directly exposes <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactorChanged"/>.
|
||||
</summary>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Wpf.WebView2.ZoomFactor"/>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2Controller.ZoomFactorChanged"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2Controller_ZoomFactorChanged(System.Object,System.Object)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2Controller's ZoomFactorChanged event.
|
||||
Unsurprisingly, it fires when the CoreWebView2Controller's ZoomFactor has been changed.
|
||||
Note that there are two distinct triggers for this:
|
||||
1) The value was changed programmatically (potentially by us, see ZoomFactorPropertyChanged).
|
||||
2) The user interacted with the CoreWebView2, e.g. CTRL + Mouse Wheel.
|
||||
Aside from propagating to our own event, we just need to update our WPF ZoomFactor property to match the CoreWebView2Controller's.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.DefaultBackgroundColorProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.DefaultBackgroundColor"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.DefaultBackgroundColor">
|
||||
<summary>
|
||||
The default background color for the WebView.
|
||||
This property directly exposes <see cref="P:Microsoft.Web.WebView2.Core.CoreWebView2Controller.DefaultBackgroundColor"/>, see its documentation for more info.
|
||||
Getting this property before the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2Controller"/> has been initialized will retrieve the last value which was
|
||||
set to it, or <c>Color.White</c> (the default) if none has been.
|
||||
The most recent value set to this property before CoreWebView2Controller has been initialized will be set on it after initialization.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.DefaultBackgroundColorPropertyChanged(System.Windows.DependencyObject,System.Windows.DependencyPropertyChangedEventArgs)">
|
||||
<summary>
|
||||
This is a callback that WPF calls when our WPF DefaultBackgroundColor property's value changes.
|
||||
Since CoreWebView2Controller does not update this property itself, this is only triggered by the
|
||||
caller setting DefaultBackgroundColor.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Web.WebView2.Wpf.WebView2.DesignModeForegroundColorProperty">
|
||||
<summary>
|
||||
The WPF <see cref="T:System.Windows.DependencyProperty"/> which backs the <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.DesignModeForegroundColor"/> property.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.DesignModeForegroundColor">
|
||||
<summary>
|
||||
The foreground color to be used in design mode.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.GoBack">
|
||||
<summary>
|
||||
Navigates the WebView to the previous page in the navigation history.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoBack"/>
|
||||
If <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> hasn't been initialized yet then does nothing.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="P:Microsoft.Web.WebView2.Core.CoreWebView2.CanGoBack"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.GoForward">
|
||||
<summary>
|
||||
Navigates the WebView to the next page in the navigation history.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoForward"/>.
|
||||
If <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> hasn't been initialized yet then does nothing.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.GoForward"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.Reload">
|
||||
<summary>
|
||||
Reloads the current page.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Reload"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> hasn't been initialized yet, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Reload"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.Stop">
|
||||
<summary>
|
||||
Stops all navigations and pending resource fetches.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Stop"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> hasn't been initialized yet, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.Stop"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.NavigateToString(System.String)">
|
||||
<summary>
|
||||
Initiates a navigation to htmlContent as source HTML of a new document.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.NavigateToString(System.String)"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> hasn't been initialized yet, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<remarks>The <c>htmlContent</c> parameter may not be larger than 2 MB (2 * 1024 * 1024 bytes) in total size. The origin of the new page is <c>about:blank</c>.</remarks>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.NavigateToString(System.String)"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.ContentLoading">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.ContentLoading"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_ContentLoading(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2ContentLoadingEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's ContentLoading event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.ExecuteScriptAsync(System.String)">
|
||||
<summary>
|
||||
Executes JavaScript code from the javaScript parameter in the current top level document rendered in the WebView.
|
||||
Equivalent to calling <see cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.ExecuteScriptAsync(System.String)"/>.
|
||||
</summary>
|
||||
<exception cref="T:System.InvalidOperationException">
|
||||
Thrown if <see cref="P:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2"/> hasn't been initialized yet, or if the calling thread isn't the thread which created this object (usually the UI thread). See <see cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/> for more info.
|
||||
May also be thrown if the browser process has crashed unexpectedly and left the control in an invalid state. We are considering throwing a different type of exception for this case in the future.
|
||||
</exception>
|
||||
<exception cref="T:System.ObjectDisposedException">Thrown if <see cref="M:Microsoft.Web.WebView2.Wpf.WebView2.Dispose(System.Boolean)"/> has already been called on the control.</exception>
|
||||
<seealso cref="M:System.Windows.Threading.DispatcherObject.VerifyAccess"/>
|
||||
<seealso cref="M:Microsoft.Web.WebView2.Core.CoreWebView2.ExecuteScriptAsync(System.String)"/>
|
||||
</member>
|
||||
<member name="E:Microsoft.Web.WebView2.Wpf.WebView2.WebMessageReceived">
|
||||
<summary>
|
||||
A wrapper around the <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/>.
|
||||
The only difference between this event and <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/> is the first parameter that's passed to handlers.
|
||||
Handlers of this event will receive the <see cref="T:Microsoft.Web.WebView2.Wpf.WebView2"/> control, whereas handlers of <see cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/> will receive the <see cref="T:Microsoft.Web.WebView2.Core.CoreWebView2"/> instance.
|
||||
</summary>
|
||||
<seealso cref="E:Microsoft.Web.WebView2.Core.CoreWebView2.WebMessageReceived"/>
|
||||
</member>
|
||||
<member name="M:Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2_WebMessageReceived(System.Object,Microsoft.Web.WebView2.Core.CoreWebView2WebMessageReceivedEventArgs)">
|
||||
<summary>
|
||||
This is an event handler for our CoreWebView2's WebMessageReceived event.
|
||||
We just need to propagate the event to WPF.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Web.WebView2.Wpf.WebView2.IsInDesignMode">
|
||||
<summary>
|
||||
True when we're in design mode and shouldn't create an underlying CoreWebView2.
|
||||
</summary>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/runtimes/win-arm64/native/WebView2Loader.dll
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/runtimes/win-x64/native/WebView2Loader.dll
vendored
Normal file
BIN
packages/Microsoft.Web.WebView2.1.0.961.33/runtimes/win-x86/native/WebView2Loader.dll
vendored
Normal file
12
packages/Microsoft.Web.WebView2.1.0.961.33/tools/VisualStudioToolsManifest.xml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<FileList>
|
||||
<File Reference = "Microsoft.Web.WebView2.Wpf.dll" >
|
||||
<ToolboxItems UIFramework="WPF" VSCategory="WebView2" BlendCategory="WebView2">
|
||||
<Item Type="Microsoft.Web.WebView2.Wpf.WebView2" />
|
||||
</ToolboxItems>
|
||||
</File>
|
||||
<File Reference = "Microsoft.Web.WebView2.WinForms.dll" >
|
||||
<ToolboxItems UIFramework="WinForms" VSCategory="WebView2">
|
||||
<Item Type="Microsoft.Web.WebView2.WinForms.WebView2" />
|
||||
</ToolboxItems>
|
||||
</File>
|
||||
</FileList>
|
||||
BIN
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/.signature.p7s
vendored
Normal file
21
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE
|
||||
60
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/ThirdPartyNotices.txt
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
THIRD PARTY SOFTWARE NOTICES AND INFORMATION
|
||||
Do Not Translate or Localize
|
||||
|
||||
This software incorporates material from third parties. Microsoft makes certain open source code available at http://3rdpartysource.microsoft.com, or you may send a check or money order for US $5.00, including the product name, the open source component name, and version number, to:
|
||||
|
||||
Source Code Compliance Team
|
||||
Microsoft Corporation
|
||||
One Microsoft Way
|
||||
Redmond, WA 98052
|
||||
USA
|
||||
|
||||
Notwithstanding any other terms, you may reverse engineer this software to the extent required to debug changes to any libraries licensed under the GNU Lesser General Public License.
|
||||
|
||||
Libc++
|
||||
|
||||
Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
Catch2
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)..\..\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
||||
2832
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/com.h
vendored
Normal file
748
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/common.h
vendored
Normal file
@ -0,0 +1,748 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
#ifndef __WIL_COMMON_INCLUDED
|
||||
#define __WIL_COMMON_INCLUDED
|
||||
|
||||
#if defined(_KERNEL_MODE ) && !defined(__WIL_MIN_KERNEL)
|
||||
// This define indicates that the WIL usage is in a kernel mode context where
|
||||
// a high degree of WIL functionality is desired.
|
||||
//
|
||||
// Use (sparingly) to change behavior based on whether WIL is being used in kernel
|
||||
// mode or user mode.
|
||||
#define WIL_KERNEL_MODE
|
||||
#endif
|
||||
|
||||
// Defining WIL_HIDE_DEPRECATED will hide everything deprecated.
|
||||
// Each wave of deprecation will add a new WIL_HIDE_DEPRECATED_YYMM number that can be used to lock deprecation at
|
||||
// a particular point, allowing components to avoid backslide and catch up to the current independently.
|
||||
#ifdef WIL_HIDE_DEPRECATED
|
||||
#define WIL_HIDE_DEPRECATED_1809
|
||||
#endif
|
||||
#ifdef WIL_HIDE_DEPRECATED_1809
|
||||
#define WIL_HIDE_DEPRECATED_1612
|
||||
#endif
|
||||
#ifdef WIL_HIDE_DEPRECATED_1612
|
||||
#define WIL_HIDE_DEPRECATED_1611
|
||||
#endif
|
||||
|
||||
// Implementation side note: ideally the deprecation would be done with the function-level declspec
|
||||
// as it allows you to utter the error text when used. The declspec works, but doing it selectively with
|
||||
// a macro makes intellisense deprecation comments not work. So we just use the #pragma deprecation.
|
||||
#ifdef WIL_WARN_DEPRECATED
|
||||
#define WIL_WARN_DEPRECATED_1809
|
||||
#endif
|
||||
#ifdef WIL_WARN_DEPRECATED_1809
|
||||
#define WIL_WARN_DEPRECATED_1612
|
||||
#endif
|
||||
#ifdef WIL_WARN_DEPRECATED_1612
|
||||
#define WIL_WARN_DEPRECATED_1611
|
||||
#endif
|
||||
#ifdef WIL_WARN_DEPRECATED_1809
|
||||
#define WIL_WARN_DEPRECATED_1809_PRAGMA(...) __pragma(deprecated(__VA_ARGS__))
|
||||
#else
|
||||
#define WIL_WARN_DEPRECATED_1809_PRAGMA(...)
|
||||
#endif
|
||||
#ifdef WIL_WARN_DEPRECATED_1611
|
||||
#define WIL_WARN_DEPRECATED_1611_PRAGMA(...) __pragma(deprecated(__VA_ARGS__))
|
||||
#else
|
||||
#define WIL_WARN_DEPRECATED_1611_PRAGMA(...)
|
||||
#endif
|
||||
#ifdef WIL_WARN_DEPRECATED_1612
|
||||
#define WIL_WARN_DEPRECATED_1612_PRAGMA(...) __pragma(deprecated(__VA_ARGS__))
|
||||
#else
|
||||
#define WIL_WARN_DEPRECATED_1612_PRAGMA(...)
|
||||
#endif
|
||||
|
||||
#if defined(_MSVC_LANG)
|
||||
#define __WI_SUPPRESS_4127_S __pragma(warning(push)) __pragma(warning(disable:4127)) __pragma(warning(disable:26498)) __pragma(warning(disable:4245))
|
||||
#define __WI_SUPPRESS_4127_E __pragma(warning(pop))
|
||||
#define __WI_SUPPRESS_NULLPTR_ANALYSIS __pragma(warning(suppress:28285)) __pragma(warning(suppress:6504))
|
||||
#define __WI_SUPPRESS_NONINIT_ANALYSIS __pragma(warning(suppress:26495))
|
||||
#define __WI_SUPPRESS_NOEXCEPT_ANALYSIS __pragma(warning(suppress:26439))
|
||||
#else
|
||||
#define __WI_SUPPRESS_4127_S
|
||||
#define __WI_SUPPRESS_4127_E
|
||||
#define __WI_SUPPRESS_NULLPTR_ANALYSIS
|
||||
#define __WI_SUPPRESS_NONINIT_ANALYSIS
|
||||
#define __WI_SUPPRESS_NOEXCEPT_ANALYSIS
|
||||
#endif
|
||||
|
||||
#include <sal.h>
|
||||
|
||||
// Some SAL remapping / decoration to better support Doxygen. Macros that look like function calls can
|
||||
// confuse Doxygen when they are used to decorate a function or variable. We simplify some of these to
|
||||
// basic macros without the function for common use cases.
|
||||
/// @cond
|
||||
#define _Success_return_ _Success_(return)
|
||||
#define _Success_true_ _Success_(true)
|
||||
#define __declspec_noinline_ __declspec(noinline)
|
||||
#define __declspec_selectany_ __declspec(selectany)
|
||||
/// @endcond
|
||||
|
||||
//! @defgroup macrobuilding Macro Composition
|
||||
//! The following macros are building blocks primarily intended for authoring other macros.
|
||||
//! @{
|
||||
|
||||
//! Re-state a macro value (indirection for composition)
|
||||
#define WI_FLATTEN(...) __VA_ARGS__
|
||||
|
||||
/// @cond
|
||||
#define __WI_PASTE_imp(a, b) a##b
|
||||
/// @endcond
|
||||
|
||||
//! This macro is for use in other macros to paste two tokens together, such as a constant and the __LINE__ macro.
|
||||
#define WI_PASTE(a, b) __WI_PASTE_imp(a, b)
|
||||
|
||||
/// @cond
|
||||
#define __WI_HAS_VA_OPT_IMPL(F, T, ...) T
|
||||
#define __WI_HAS_VA_OPT_(...) __WI_HAS_VA_OPT_IMPL(__VA_OPT__(0,) 1, 0)
|
||||
/// @endcond
|
||||
|
||||
//! Evaluates to '1' when support for '__VA_OPT__' is available, else '0'
|
||||
#define WI_HAS_VA_OPT __WI_HAS_VA_OPT_(unused)
|
||||
|
||||
/// @cond
|
||||
#define __WI_ARGS_COUNT1(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24, A25, A26, A27, A28, A29, \
|
||||
A30, A31, A32, A33, A34, A35, A36, A37, A38, A39, A40, A41, A42, A43, A44, A45, A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, A57, A58, A59, \
|
||||
A60, A61, A62, A63, A64, A65, A66, A67, A68, A69, A70, A71, A72, A73, A74, A75, A76, A77, A78, A79, A80, A81, A82, A83, A84, A85, A86, A87, A88, A89, \
|
||||
A90, A91, A92, A93, A94, A95, A96, A97, A98, A99, count, ...) count
|
||||
#define __WI_ARGS_COUNT0(...) WI_FLATTEN(__WI_ARGS_COUNT1(__VA_ARGS__, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, \
|
||||
79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \
|
||||
39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
|
||||
#define __WI_ARGS_COUNT_PREFIX(...) 0, __VA_ARGS__
|
||||
/// @endcond
|
||||
|
||||
//! This variadic macro returns the number of arguments passed to it (up to 99).
|
||||
#if WI_HAS_VA_OPT
|
||||
#define WI_ARGS_COUNT(...) __WI_ARGS_COUNT0(0 __VA_OPT__(, __VA_ARGS__))
|
||||
#else
|
||||
#define WI_ARGS_COUNT(...) __WI_ARGS_COUNT0(__WI_ARGS_COUNT_PREFIX(__VA_ARGS__))
|
||||
#endif
|
||||
|
||||
/// @cond
|
||||
#define __WI_FOR_imp0( fn)
|
||||
#define __WI_FOR_imp1( fn, arg) fn(arg)
|
||||
#define __WI_FOR_imp2( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp1(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp3( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp2(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp4( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp3(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp5( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp4(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp6( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp5(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp7( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp6(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp8( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp7(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp9( fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp8(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp10(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp9(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp11(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp10(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp12(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp11(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp13(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp12(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp14(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp13(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp15(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp14(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp16(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp15(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp17(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp16(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp18(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp17(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp19(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp18(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp20(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp19(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp21(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp20(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp22(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp21(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp23(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp22(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp24(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp23(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp25(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp24(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp26(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp25(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp27(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp26(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp28(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp27(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp29(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp28(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp30(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp29(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp31(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp30(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp32(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp31(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp33(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp32(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp34(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp33(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp35(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp34(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp36(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp35(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp37(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp36(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp38(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp37(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp39(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp38(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp40(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp39(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp41(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp40(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp42(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp41(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp43(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp42(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp44(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp43(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp45(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp44(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp46(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp45(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp47(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp46(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp48(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp47(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp49(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp48(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp50(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp49(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp51(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp50(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp52(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp51(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp53(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp52(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp54(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp53(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp55(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp54(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp56(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp55(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp57(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp56(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp58(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp57(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp59(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp58(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp60(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp59(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp61(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp60(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp62(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp61(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp63(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp62(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp64(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp63(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp65(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp64(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp66(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp65(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp67(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp66(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp68(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp67(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp69(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp68(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp70(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp69(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp71(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp70(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp72(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp71(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp73(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp72(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp74(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp73(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp75(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp74(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp76(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp75(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp77(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp76(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp78(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp77(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp79(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp78(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp80(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp79(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp81(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp80(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp82(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp81(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp83(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp82(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp84(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp83(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp85(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp84(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp86(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp85(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp87(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp86(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp88(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp87(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp89(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp88(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp90(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp89(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp91(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp90(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp92(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp91(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp93(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp92(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp94(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp93(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp95(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp94(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp96(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp95(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp97(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp96(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp98(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp97(fn, __VA_ARGS__))
|
||||
#define __WI_FOR_imp99(fn, arg, ...) fn(arg) WI_FLATTEN(__WI_FOR_imp98(fn, __VA_ARGS__))
|
||||
|
||||
#define __WI_FOR_imp(n, fnAndArgs) WI_PASTE(__WI_FOR_imp, n) fnAndArgs
|
||||
/// @endcond
|
||||
|
||||
//! Iterates through each of the given arguments invoking the specified macro against each one.
|
||||
#define WI_FOREACH(fn, ...) __WI_FOR_imp(WI_ARGS_COUNT(__VA_ARGS__), (fn, ##__VA_ARGS__))
|
||||
|
||||
//! Dispatches a single macro name to separate macros based on the number of arguments passed to it.
|
||||
#define WI_MACRO_DISPATCH(name, ...) WI_PASTE(WI_PASTE(name, WI_ARGS_COUNT(__VA_ARGS__)), (__VA_ARGS__))
|
||||
|
||||
//! @} // Macro composition helpers
|
||||
|
||||
#if !defined(__cplusplus) || defined(__WIL_MIN_KERNEL)
|
||||
|
||||
#define WI_ODR_PRAGMA(NAME, TOKEN)
|
||||
#define WI_NOEXCEPT
|
||||
|
||||
#else
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4714) // __forceinline not honored
|
||||
|
||||
// DO NOT add *any* further includes to this file -- there should be no dependencies from its usage
|
||||
#include "wistd_type_traits.h"
|
||||
|
||||
//! This macro inserts ODR violation protection; the macro allows it to be compatible with straight "C" code
|
||||
#define WI_ODR_PRAGMA(NAME, TOKEN) __pragma(detect_mismatch("ODR_violation_" NAME "_mismatch", TOKEN))
|
||||
|
||||
#ifdef WIL_KERNEL_MODE
|
||||
WI_ODR_PRAGMA("WIL_KERNEL_MODE", "1")
|
||||
#else
|
||||
WI_ODR_PRAGMA("WIL_KERNEL_MODE", "0")
|
||||
#endif
|
||||
|
||||
#if defined(_CPPUNWIND) && !defined(WIL_SUPPRESS_EXCEPTIONS)
|
||||
/** This define is automatically set when exceptions are enabled within wil.
|
||||
It is automatically defined when your code is compiled with exceptions enabled (via checking for the built-in
|
||||
_CPPUNWIND flag) unless you explicitly define WIL_SUPPRESS_EXCEPTIONS ahead of including your first wil
|
||||
header. All exception-based WIL methods and classes are included behind:
|
||||
~~~~
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
// code
|
||||
#endif
|
||||
~~~~
|
||||
This enables exception-free code to directly include WIL headers without worrying about exception-based
|
||||
routines suddenly becoming available. */
|
||||
#define WIL_ENABLE_EXCEPTIONS
|
||||
#endif
|
||||
/// @endcond
|
||||
|
||||
/// @cond
|
||||
#if defined(WIL_EXCEPTION_MODE)
|
||||
static_assert(WIL_EXCEPTION_MODE <= 2, "Invalid exception mode");
|
||||
#elif !defined(WIL_LOCK_EXCEPTION_MODE)
|
||||
#define WIL_EXCEPTION_MODE 0 // default, can link exception-based and non-exception based libraries together
|
||||
#pragma detect_mismatch("ODR_violation_WIL_EXCEPTION_MODE_mismatch", "0")
|
||||
#elif defined(WIL_ENABLE_EXCEPTIONS)
|
||||
#define WIL_EXCEPTION_MODE 1 // new code optimization: ONLY support linking libraries together that have exceptions enabled
|
||||
#pragma detect_mismatch("ODR_violation_WIL_EXCEPTION_MODE_mismatch", "1")
|
||||
#else
|
||||
#define WIL_EXCEPTION_MODE 2 // old code optimization: ONLY support linking libraries that are NOT using exceptions
|
||||
#pragma detect_mismatch("ODR_violation_WIL_EXCEPTION_MODE_mismatch", "2")
|
||||
#endif
|
||||
|
||||
#if WIL_EXCEPTION_MODE == 1 && !defined(WIL_ENABLE_EXCEPTIONS)
|
||||
#error Must enable exceptions when WIL_EXCEPTION_MODE == 1
|
||||
#endif
|
||||
|
||||
// block for documentation only
|
||||
#if defined(WIL_DOXYGEN)
|
||||
/** This define can be explicitly set to disable exception usage within wil.
|
||||
Normally this define is never needed as the WIL_ENABLE_EXCEPTIONS macro is enabled automatically by looking
|
||||
at _CPPUNWIND. If your code compiles with exceptions enabled, but does not want to enable the exception-based
|
||||
classes and methods from WIL, define this macro ahead of including the first WIL header. */
|
||||
#define WIL_SUPPRESS_EXCEPTIONS
|
||||
|
||||
/** This define can be explicitly set to lock the process exception mode to WIL_ENABLE_EXCEPTIONS.
|
||||
Locking the exception mode provides optimizations to exception barriers, staging hooks and DLL load costs as it eliminates the need to
|
||||
do copy-on-write initialization of various function pointers and the necessary indirection that's done within WIL to avoid ODR violations
|
||||
when linking libraries together with different exception handling semantics. */
|
||||
#define WIL_LOCK_EXCEPTION_MODE
|
||||
|
||||
/** This define explicit sets the exception mode for the process to control optimizations.
|
||||
Three exception modes are available:
|
||||
0) This is the default. This enables a binary to link both exception-based and non-exception based libraries together that
|
||||
use WIL. This adds overhead to exception barriers, DLL copy on write pages and indirection through function pointers to avoid ODR
|
||||
violations when linking libraries together with different exception handling semantics.
|
||||
1) Prefer this setting when it can be used. This locks the binary to only supporting libraries which were built with exceptions enabled.
|
||||
2) This locks the binary to libraries built without exceptions. */
|
||||
#define WIL_EXCEPTION_MODE
|
||||
#endif
|
||||
|
||||
#if (__cplusplus >= 201703) || (_MSVC_LANG >= 201703)
|
||||
#define WIL_HAS_CXX_17 1
|
||||
#else
|
||||
#define WIL_HAS_CXX_17 0
|
||||
#endif
|
||||
|
||||
// Until we'll have C++17 enabled in our code base, we're falling back to SAL
|
||||
#define WI_NODISCARD __WI_LIBCPP_NODISCARD_ATTRIBUTE
|
||||
|
||||
#define __R_ENABLE_IF_IS_CLASS(ptrType) wistd::enable_if_t<wistd::is_class<ptrType>::value, void*> = (void*)0
|
||||
#define __R_ENABLE_IF_IS_NOT_CLASS(ptrType) wistd::enable_if_t<!wistd::is_class<ptrType>::value, void*> = (void*)0
|
||||
|
||||
//! @defgroup bitwise Bitwise Inspection and Manipulation
|
||||
//! Bitwise helpers to improve readability and reduce the error rate of bitwise operations.
|
||||
//! Several macros have been constructed to assist with bitwise inspection and manipulation. These macros exist
|
||||
//! for two primary purposes:
|
||||
//!
|
||||
//! 1. To improve the readability of bitwise comparisons and manipulation.
|
||||
//!
|
||||
//! The macro names are the more concise, readable form of what's being done and do not require that any flags
|
||||
//! or variables be specified multiple times for the comparisons.
|
||||
//!
|
||||
//! 2. To reduce the error rate associated with bitwise operations.
|
||||
//!
|
||||
//! The readability improvements naturally lend themselves to this by cutting down the number of concepts.
|
||||
//! Using `WI_IsFlagSet(var, MyEnum::Flag)` rather than `((var & MyEnum::Flag) == MyEnum::Flag)` removes the comparison
|
||||
//! operator and repetition in the flag value.
|
||||
//!
|
||||
//! Additionally, these macros separate single flag operations (which tend to be the most common) from multi-flag
|
||||
//! operations so that compile-time errors are generated for bitwise operations which are likely incorrect,
|
||||
//! such as: `WI_IsFlagSet(var, MyEnum::None)` or `WI_IsFlagSet(var, MyEnum::ValidMask)`.
|
||||
//!
|
||||
//! Note that the single flag helpers should be used when a compile-time constant single flag is being manipulated. These
|
||||
//! helpers provide compile-time errors on misuse and should be preferred over the multi-flag helpers. The multi-flag helpers
|
||||
//! should be used when multiple flags are being used simultaneously or when the flag values are not compile-time constants.
|
||||
//!
|
||||
//! Common example usage (manipulation of flag variables):
|
||||
//! ~~~~
|
||||
//! WI_SetFlag(m_flags, MyFlags::Foo); // Set a single flag in the given variable
|
||||
//! WI_SetAllFlags(m_flags, MyFlags::Foo | MyFlags::Bar); // Set one or more flags
|
||||
//! WI_ClearFlagIf(m_flags, MyFlags::Bar, isBarClosed); // Conditionally clear a single flag based upon a bool
|
||||
//! WI_ClearAllFlags(m_flags, MyFlags::Foo | MyFlags::Bar); // Clear one or more flags from the given variable
|
||||
//! WI_ToggleFlag(m_flags, MyFlags::Foo); // Toggle (change to the opposite value) a single flag
|
||||
//! WI_UpdateFlag(m_flags, MyFlags::Bar, isBarClosed); // Sets or Clears a single flag from the given variable based upon a bool value
|
||||
//! WI_UpdateFlagsInMask(m_flags, flagsMask, newFlagValues); // Sets or Clears the flags in flagsMask to the masked values from newFlagValues
|
||||
//! ~~~~
|
||||
//! Common example usage (inspection of flag variables):
|
||||
//! ~~~~
|
||||
//! if (WI_IsFlagSet(m_flags, MyFlags::Foo)) // Is a single flag set in the given variable?
|
||||
//! if (WI_IsAnyFlagSet(m_flags, MyFlags::Foo | MyFlags::Bar)) // Is at least one flag from the given mask set?
|
||||
//! if (WI_AreAllFlagsClear(m_flags, MyFlags::Foo | MyFlags::Bar)) // Are all flags in the given list clear?
|
||||
//! if (WI_IsSingleFlagSet(m_flags)) // Is *exactly* one flag set in the given variable?
|
||||
//! ~~~~
|
||||
//! @{
|
||||
|
||||
//! Returns the unsigned type of the same width and numeric value as the given enum
|
||||
#define WI_EnumValue(val) static_cast<::wil::integral_from_enum<decltype(val)>>(val)
|
||||
//! Validates that exactly ONE bit is set in compile-time constant `flag`
|
||||
#define WI_StaticAssertSingleBitSet(flag) static_cast<decltype(flag)>(::wil::details::verify_single_flag_helper<static_cast<unsigned long long>(WI_EnumValue(flag))>::value)
|
||||
|
||||
//! @name Bitwise manipulation macros
|
||||
//! @{
|
||||
|
||||
//! Set zero or more bitflags specified by `flags` in the variable `var`.
|
||||
#define WI_SetAllFlags(var, flags) ((var) |= (flags))
|
||||
//! Set a single compile-time constant `flag` in the variable `var`.
|
||||
#define WI_SetFlag(var, flag) WI_SetAllFlags(var, WI_StaticAssertSingleBitSet(flag))
|
||||
//! Conditionally sets a single compile-time constant `flag` in the variable `var` only if `condition` is true.
|
||||
#define WI_SetFlagIf(var, flag, condition) do { if (wil::verify_bool(condition)) { WI_SetFlag(var, flag); } } while ((void)0, 0)
|
||||
|
||||
//! Clear zero or more bitflags specified by `flags` from the variable `var`.
|
||||
#define WI_ClearAllFlags(var, flags) ((var) &= ~(flags))
|
||||
//! Clear a single compile-time constant `flag` from the variable `var`.
|
||||
#define WI_ClearFlag(var, flag) WI_ClearAllFlags(var, WI_StaticAssertSingleBitSet(flag))
|
||||
//! Conditionally clear a single compile-time constant `flag` in the variable `var` only if `condition` is true.
|
||||
#define WI_ClearFlagIf(var, flag, condition) do { if (wil::verify_bool(condition)) { WI_ClearFlag(var, flag); } } while ((void)0, 0)
|
||||
|
||||
//! Changes a single compile-time constant `flag` in the variable `var` to be set if `isFlagSet` is true or cleared if `isFlagSet` is false.
|
||||
#define WI_UpdateFlag(var, flag, isFlagSet) (wil::verify_bool(isFlagSet) ? WI_SetFlag(var, flag) : WI_ClearFlag(var, flag))
|
||||
//! Changes only the flags specified by `flagsMask` in the variable `var` to match the corresponding flags in `newFlags`.
|
||||
#define WI_UpdateFlagsInMask(var, flagsMask, newFlags) wil::details::UpdateFlagsInMaskHelper(var, flagsMask, newFlags)
|
||||
|
||||
//! Toggles (XOR the value) of multiple bitflags specified by `flags` in the variable `var`.
|
||||
#define WI_ToggleAllFlags(var, flags) ((var) ^= (flags))
|
||||
//! Toggles (XOR the value) of a single compile-time constant `flag` in the variable `var`.
|
||||
#define WI_ToggleFlag(var, flag) WI_ToggleAllFlags(var, WI_StaticAssertSingleBitSet(flag))
|
||||
//! @} // bitwise manipulation macros
|
||||
|
||||
//! @name Bitwise inspection macros
|
||||
//! @{
|
||||
|
||||
//! Evaluates as true if every bitflag specified in `flags` is set within `val`.
|
||||
#define WI_AreAllFlagsSet(val, flags) wil::details::AreAllFlagsSetHelper(val, flags)
|
||||
//! Evaluates as true if one or more bitflags specified in `flags` are set within `val`.
|
||||
#define WI_IsAnyFlagSet(val, flags) (static_cast<decltype((val) & (flags))>(WI_EnumValue(val) & WI_EnumValue(flags)) != static_cast<decltype((val) & (flags))>(0))
|
||||
//! Evaluates as true if a single compile-time constant `flag` is set within `val`.
|
||||
#define WI_IsFlagSet(val, flag) WI_IsAnyFlagSet(val, WI_StaticAssertSingleBitSet(flag))
|
||||
|
||||
//! Evaluates as true if every bitflag specified in `flags` is clear within `val`.
|
||||
#define WI_AreAllFlagsClear(val, flags) (static_cast<decltype((val) & (flags))>(WI_EnumValue(val) & WI_EnumValue(flags)) == static_cast<decltype((val) & (flags))>(0))
|
||||
//! Evaluates as true if one or more bitflags specified in `flags` are clear within `val`.
|
||||
#define WI_IsAnyFlagClear(val, flags) (!wil::details::AreAllFlagsSetHelper(val, flags))
|
||||
//! Evaluates as true if a single compile-time constant `flag` is clear within `val`.
|
||||
#define WI_IsFlagClear(val, flag) WI_AreAllFlagsClear(val, WI_StaticAssertSingleBitSet(flag))
|
||||
|
||||
//! Evaluates as true if exactly one bit (any bit) is set within `val`.
|
||||
#define WI_IsSingleFlagSet(val) wil::details::IsSingleFlagSetHelper(val)
|
||||
//! Evaluates as true if exactly one bit from within the specified `mask` is set within `val`.
|
||||
#define WI_IsSingleFlagSetInMask(val, mask) wil::details::IsSingleFlagSetHelper((val) & (mask))
|
||||
//! Evaluates as true if exactly one bit (any bit) is set within `val` or if there are no bits set within `val`.
|
||||
#define WI_IsClearOrSingleFlagSet(val) wil::details::IsClearOrSingleFlagSetHelper(val)
|
||||
//! Evaluates as true if exactly one bit from within the specified `mask` is set within `val` or if there are no bits from `mask` set within `val`.
|
||||
#define WI_IsClearOrSingleFlagSetInMask(val, mask) wil::details::IsClearOrSingleFlagSetHelper((val) & (mask))
|
||||
//! @}
|
||||
|
||||
#if defined(WIL_DOXYGEN)
|
||||
/** This macro provides a C++ header with a guaranteed initialization function.
|
||||
Normally, were a global object's constructor used for this purpose, the optimizer/linker might throw
|
||||
the object away if it's unreferenced (which throws away the side-effects that the initialization function
|
||||
was trying to achieve). Using this macro forces linker inclusion of a variable that's initialized by the
|
||||
provided function to elide that optimization.
|
||||
//!
|
||||
This functionality is primarily provided as a building block for header-based libraries (such as WIL)
|
||||
to be able to layer additional functionality into other libraries by their mere inclusion. Alternative models
|
||||
of initialization should be used whenever they are available.
|
||||
~~~~
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
WI_HEADER_INITITALIZATION_FUNCTION(InitializeDesktopFamilyApis, []
|
||||
{
|
||||
g_pfnGetModuleName = GetCurrentModuleName;
|
||||
g_pfnFailFastInLoaderCallout = FailFastInLoaderCallout;
|
||||
return 1;
|
||||
});
|
||||
#endif
|
||||
~~~~
|
||||
The above example is used within WIL to decide whether or not the library containing WIL is allowed to use
|
||||
desktop APIs. Building this functionality as #IFDEFs within functions would create ODR violations, whereas
|
||||
doing it with global function pointers and header initialization allows a runtime determination. */
|
||||
#define WI_HEADER_INITITALIZATION_FUNCTION(name, fn)
|
||||
#elif defined(_M_IX86)
|
||||
#define WI_HEADER_INITITALIZATION_FUNCTION(name, fn) \
|
||||
extern "C" { __declspec(selectany) unsigned char g_header_init_ ## name = static_cast<unsigned char>(fn()); } \
|
||||
__pragma(comment(linker, "/INCLUDE:_g_header_init_" #name))
|
||||
#elif defined(_M_IA64) || defined(_M_AMD64) || defined(_M_ARM) || defined(_M_ARM64)
|
||||
#define WI_HEADER_INITITALIZATION_FUNCTION(name, fn) \
|
||||
extern "C" { __declspec(selectany) unsigned char g_header_init_ ## name = static_cast<unsigned char>(fn()); } \
|
||||
__pragma(comment(linker, "/INCLUDE:g_header_init_" #name))
|
||||
#else
|
||||
#error linker pragma must include g_header_init variation
|
||||
#endif
|
||||
|
||||
|
||||
/** All Windows Implementation Library classes and functions are located within the "wil" namespace.
|
||||
The 'wil' namespace is an intentionally short name as the intent is for code to be able to reference
|
||||
the namespace directly (example: `wil::srwlock lock;`) without a using statement. Resist adding a using
|
||||
statement for wil to avoid introducing potential name collisions between wil and other namespaces. */
|
||||
namespace wil
|
||||
{
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
template <typename T>
|
||||
class pointer_range
|
||||
{
|
||||
public:
|
||||
pointer_range(T begin_, T end_) : m_begin(begin_), m_end(end_) {}
|
||||
T begin() const { return m_begin; }
|
||||
T end() const { return m_end; }
|
||||
private:
|
||||
T m_begin;
|
||||
T m_end;
|
||||
};
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
/** Enables using range-based for between a begin and end object pointer.
|
||||
~~~~
|
||||
for (auto& obj : make_range(objPointerBegin, objPointerEnd)) { }
|
||||
~~~~ */
|
||||
template <typename T>
|
||||
details::pointer_range<T> make_range(T begin, T end)
|
||||
{
|
||||
return details::pointer_range<T>(begin, end);
|
||||
}
|
||||
|
||||
/** Enables using range-based for on a range when given the base pointer and the number of objects in the range.
|
||||
~~~~
|
||||
for (auto& obj : make_range(objPointer, objCount)) { }
|
||||
~~~~ */
|
||||
template <typename T>
|
||||
details::pointer_range<T> make_range(T begin, size_t count)
|
||||
{
|
||||
return details::pointer_range<T>(begin, begin + count);
|
||||
}
|
||||
|
||||
|
||||
//! @defgroup outparam Output Parameters
|
||||
//! Improve the conciseness of assigning values to optional output parameters.
|
||||
//! @{
|
||||
|
||||
/** Assign the given value to an optional output parameter.
|
||||
Makes code more concise by removing trivial `if (outParam)` blocks. */
|
||||
template <typename T>
|
||||
inline void assign_to_opt_param(_Out_opt_ T *outParam, T val)
|
||||
{
|
||||
if (outParam != nullptr)
|
||||
{
|
||||
*outParam = val;
|
||||
}
|
||||
}
|
||||
|
||||
/** Assign NULL to an optional output pointer parameter.
|
||||
Makes code more concise by removing trivial `if (outParam)` blocks. */
|
||||
template <typename T>
|
||||
inline void assign_null_to_opt_param(_Out_opt_ T *outParam)
|
||||
{
|
||||
if (outParam != nullptr)
|
||||
{
|
||||
*outParam = nullptr;
|
||||
}
|
||||
}
|
||||
//! @} // end output parameter helpers
|
||||
|
||||
/** Performs a logical or of the given variadic template parameters allowing indirect compile-time boolean evaluation.
|
||||
Example usage:
|
||||
~~~~
|
||||
template <unsigned int... Rest>
|
||||
struct FeatureRequiredBy
|
||||
{
|
||||
static const bool enabled = wil::variadic_logical_or<WilFeature<Rest>::enabled...>::value;
|
||||
};
|
||||
~~~~ */
|
||||
template <bool...> struct variadic_logical_or;
|
||||
/// @cond
|
||||
template <> struct variadic_logical_or<> : wistd::false_type { };
|
||||
template <bool... Rest> struct variadic_logical_or<true, Rest...> : wistd::true_type { };
|
||||
template <bool... Rest> struct variadic_logical_or<false, Rest...> : variadic_logical_or<Rest...>::type { };
|
||||
/// @endcond
|
||||
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
template <unsigned long long flag>
|
||||
struct verify_single_flag_helper
|
||||
{
|
||||
static_assert((flag != 0) && ((flag & (flag - 1)) == 0), "Single flag expected, zero or multiple flags found");
|
||||
static const unsigned long long value = flag;
|
||||
};
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
|
||||
//! @defgroup typesafety Type Validation
|
||||
//! Helpers to validate variable types to prevent accidental, but allowed type conversions.
|
||||
//! These helpers are most useful when building macros that accept a particular type. Putting these functions around the types accepted
|
||||
//! prior to pushing that type through to a function (or using it within the macro) allows the macro to add an additional layer of type
|
||||
//! safety that would ordinarily be stripped away by C++ implicit conversions. This system is extensively used in the error handling helper
|
||||
//! macros to validate the types given to various macro parameters.
|
||||
//! @{
|
||||
|
||||
/** Verify that `val` can be evaluated as a logical bool.
|
||||
Other types will generate an intentional compilation error. Allowed types for a logical bool are bool, BOOL,
|
||||
boolean, BOOLEAN, and classes with an explicit bool cast.
|
||||
@param val The logical bool expression
|
||||
@return A C++ bool representing the evaluation of `val`. */
|
||||
template <typename T, __R_ENABLE_IF_IS_CLASS(T)>
|
||||
_Post_satisfies_(return == static_cast<bool>(val))
|
||||
__forceinline constexpr bool verify_bool(const T& val)
|
||||
{
|
||||
return static_cast<bool>(val);
|
||||
}
|
||||
|
||||
template <typename T, __R_ENABLE_IF_IS_NOT_CLASS(T)>
|
||||
__forceinline constexpr bool verify_bool(T /*val*/)
|
||||
{
|
||||
static_assert(!wistd::is_same<T, T>::value, "Wrong Type: bool/BOOL/BOOLEAN/boolean expected");
|
||||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
_Post_satisfies_(return == val)
|
||||
__forceinline constexpr bool verify_bool<bool>(bool val)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
template <>
|
||||
_Post_satisfies_(return == (val != 0))
|
||||
__forceinline constexpr bool verify_bool<int>(int val)
|
||||
{
|
||||
return (val != 0);
|
||||
}
|
||||
|
||||
template <>
|
||||
_Post_satisfies_(return == !!val)
|
||||
__forceinline constexpr bool verify_bool<unsigned char>(unsigned char val)
|
||||
{
|
||||
return !!val;
|
||||
}
|
||||
|
||||
/** Verify that `val` is a Win32 BOOL value.
|
||||
Other types (including other logical bool expressions) will generate an intentional compilation error. Note that this will
|
||||
accept any `int` value as long as that is the underlying typedef behind `BOOL`.
|
||||
@param val The Win32 BOOL returning expression
|
||||
@return A Win32 BOOL representing the evaluation of `val`. */
|
||||
template <typename T>
|
||||
_Post_satisfies_(return == val)
|
||||
__forceinline constexpr int verify_BOOL(T val)
|
||||
{
|
||||
// Note: Written in terms of 'int' as BOOL is actually: typedef int BOOL;
|
||||
static_assert((wistd::is_same<T, int>::value), "Wrong Type: BOOL expected");
|
||||
return val;
|
||||
}
|
||||
|
||||
/** Verify that `hr` is an HRESULT value.
|
||||
Other types will generate an intentional compilation error. Note that this will accept any `long` value as that is the
|
||||
underlying typedef behind HRESULT.
|
||||
//!
|
||||
Note that occasionally you might run into an HRESULT which is directly defined with a #define, such as:
|
||||
~~~~
|
||||
#define UIA_E_NOTSUPPORTED 0x80040204
|
||||
~~~~
|
||||
Though this looks like an `HRESULT`, this is actually an `unsigned long` (the hex specification forces this). When
|
||||
these are encountered and they are NOT in the public SDK (have not yet shipped to the public), then you should change
|
||||
their definition to match the manner in which `HRESULT` constants are defined in winerror.h:
|
||||
~~~~
|
||||
#define E_NOTIMPL _HRESULT_TYPEDEF_(0x80004001L)
|
||||
~~~~
|
||||
When these are encountered in the public SDK, their type should not be changed and you should use a static_cast
|
||||
to use this value in a macro that utilizes `verify_hresult`, for example:
|
||||
~~~~
|
||||
RETURN_HR_IF(static_cast<HRESULT>(UIA_E_NOTSUPPORTED), (patternId != UIA_DragPatternId));
|
||||
~~~~
|
||||
@param val The HRESULT returning expression
|
||||
@return An HRESULT representing the evaluation of `val`. */
|
||||
template <typename T>
|
||||
_Post_satisfies_(return == hr)
|
||||
inline constexpr long verify_hresult(T hr)
|
||||
{
|
||||
// Note: Written in terms of 'int' as HRESULT is actually: typedef _Return_type_success_(return >= 0) long HRESULT
|
||||
static_assert(wistd::is_same<T, long>::value, "Wrong Type: HRESULT expected");
|
||||
return hr;
|
||||
}
|
||||
/// @} // end type validation routines
|
||||
|
||||
/// @cond
|
||||
// Implementation details for macros and helper functions... do not use directly.
|
||||
namespace details
|
||||
{
|
||||
// Use size-specific casts to avoid sign extending numbers -- avoid warning C4310: cast truncates constant value
|
||||
#define __WI_MAKE_UNSIGNED(val) \
|
||||
(__pragma(warning(push)) __pragma(warning(disable: 4310 4309)) (sizeof(val) == 1 ? static_cast<unsigned char>(val) : \
|
||||
sizeof(val) == 2 ? static_cast<unsigned short>(val) : \
|
||||
sizeof(val) == 4 ? static_cast<unsigned long>(val) : \
|
||||
static_cast<unsigned long long>(val)) __pragma(warning(pop)))
|
||||
#define __WI_IS_UNSIGNED_SINGLE_FLAG_SET(val) ((val) && !((val) & ((val) - 1)))
|
||||
#define __WI_IS_SINGLE_FLAG_SET(val) __WI_IS_UNSIGNED_SINGLE_FLAG_SET(__WI_MAKE_UNSIGNED(val))
|
||||
|
||||
template <typename TVal, typename TFlags>
|
||||
__forceinline constexpr bool AreAllFlagsSetHelper(TVal val, TFlags flags)
|
||||
{
|
||||
return ((val & flags) == static_cast<decltype(val & flags)>(flags));
|
||||
}
|
||||
|
||||
template <typename TVal>
|
||||
__forceinline constexpr bool IsSingleFlagSetHelper(TVal val)
|
||||
{
|
||||
return __WI_IS_SINGLE_FLAG_SET(val);
|
||||
}
|
||||
|
||||
template <typename TVal>
|
||||
__forceinline constexpr bool IsClearOrSingleFlagSetHelper(TVal val)
|
||||
{
|
||||
return ((val == static_cast<wistd::remove_reference_t<TVal>>(0)) || IsSingleFlagSetHelper(val));
|
||||
}
|
||||
|
||||
template <typename TVal, typename TMask, typename TFlags>
|
||||
__forceinline constexpr void UpdateFlagsInMaskHelper(_Inout_ TVal& val, TMask mask, TFlags flags)
|
||||
{
|
||||
val = static_cast<wistd::remove_reference_t<TVal>>((val & ~mask) | (flags & mask));
|
||||
}
|
||||
|
||||
template <long>
|
||||
struct variable_size;
|
||||
|
||||
template <>
|
||||
struct variable_size<1>
|
||||
{
|
||||
typedef unsigned char type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct variable_size<2>
|
||||
{
|
||||
typedef unsigned short type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct variable_size<4>
|
||||
{
|
||||
typedef unsigned long type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct variable_size<8>
|
||||
{
|
||||
typedef unsigned long long type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct variable_size_mapping
|
||||
{
|
||||
typedef typename variable_size<sizeof(T)>::type type;
|
||||
};
|
||||
} // details
|
||||
/// @endcond
|
||||
|
||||
/** Defines the unsigned type of the same width (1, 2, 4, or 8 bytes) as the given type.
|
||||
This allows code to generically convert any enum class to it's corresponding underlying type. */
|
||||
template <typename T>
|
||||
using integral_from_enum = typename details::variable_size_mapping<T>::type;
|
||||
} // wil
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
#endif // __cplusplus
|
||||
#endif // __WIL_COMMON_INCLUDED
|
||||
251
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/cppwinrt.h
vendored
Normal file
@ -0,0 +1,251 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
#ifndef __WIL_CPPWINRT_INCLUDED
|
||||
#define __WIL_CPPWINRT_INCLUDED
|
||||
|
||||
#include "common.h"
|
||||
#include <windows.h>
|
||||
#include <unknwn.h>
|
||||
#include <hstring.h>
|
||||
|
||||
// WIL and C++/WinRT use two different exception types for communicating HRESULT failures. Thus, both libraries need to
|
||||
// understand how to translate these exception types into the correct HRESULT values at the ABI boundary. Prior to
|
||||
// C++/WinRT "2.0" this was accomplished by injecting the WINRT_EXTERNAL_CATCH_CLAUSE macro - that WIL defines below -
|
||||
// into its exception handler (winrt::to_hresult). Starting with C++/WinRT "2.0" this mechanism has shifted to a global
|
||||
// function pointer - winrt_to_hresult_handler - that WIL sets automatically when this header is included and
|
||||
// 'CPPWINRT_SUPPRESS_STATIC_INITIALIZERS' is not defined.
|
||||
|
||||
/// @cond
|
||||
namespace wil::details
|
||||
{
|
||||
// Since the C++/WinRT version macro is a string...
|
||||
inline constexpr int major_version_from_string(const char* versionString)
|
||||
{
|
||||
int result = 0;
|
||||
auto str = versionString;
|
||||
while ((*str >= '0') && (*str <= '9'))
|
||||
{
|
||||
result = result * 10 + (*str - '0');
|
||||
++str;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
#ifdef CPPWINRT_VERSION
|
||||
// Prior to C++/WinRT "2.0" this header needed to be included before 'winrt/base.h' so that our definition of
|
||||
// 'WINRT_EXTERNAL_CATCH_CLAUSE' would get picked up in the implementation of 'winrt::to_hresult'. This is no longer
|
||||
// problematic, so only emit an error when using a version of C++/WinRT prior to 2.0
|
||||
static_assert(::wil::details::major_version_from_string(CPPWINRT_VERSION) >= 2,
|
||||
"Please include wil/cppwinrt.h before including any C++/WinRT headers");
|
||||
#endif
|
||||
|
||||
// NOTE: Will eventually be removed once C++/WinRT 2.0 use can be assumed
|
||||
#ifdef WINRT_EXTERNAL_CATCH_CLAUSE
|
||||
#define __WI_CONFLICTING_WINRT_EXTERNAL_CATCH_CLAUSE 1
|
||||
#else
|
||||
#define WINRT_EXTERNAL_CATCH_CLAUSE \
|
||||
catch (const wil::ResultException& e) \
|
||||
{ \
|
||||
return winrt::hresult_error(e.GetErrorCode(), winrt::to_hstring(e.what())).to_abi(); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "result_macros.h"
|
||||
#include <winrt/base.h>
|
||||
|
||||
#if __WI_CONFLICTING_WINRT_EXTERNAL_CATCH_CLAUSE
|
||||
static_assert(::wil::details::major_version_from_string(CPPWINRT_VERSION) >= 2,
|
||||
"C++/WinRT external catch clause already defined outside of WIL");
|
||||
#endif
|
||||
|
||||
// In C++/WinRT 2.0 and beyond, this function pointer exists. In earlier versions it does not. It's much easier to avoid
|
||||
// linker errors than it is to SFINAE on variable existence, so we declare the variable here, but are careful not to
|
||||
// use it unless the version of C++/WinRT is high enough
|
||||
extern std::int32_t(__stdcall* winrt_to_hresult_handler)(void*) noexcept;
|
||||
|
||||
/// @cond
|
||||
namespace wil::details
|
||||
{
|
||||
inline void MaybeGetExceptionString(
|
||||
const winrt::hresult_error& exception,
|
||||
_Out_writes_opt_(debugStringChars) PWSTR debugString,
|
||||
_When_(debugString != nullptr, _Pre_satisfies_(debugStringChars > 0)) size_t debugStringChars)
|
||||
{
|
||||
if (debugString)
|
||||
{
|
||||
StringCchPrintfW(debugString, debugStringChars, L"winrt::hresult_error: %ls", exception.message().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
inline HRESULT __stdcall ResultFromCaughtException_CppWinRt(
|
||||
_Inout_updates_opt_(debugStringChars) PWSTR debugString,
|
||||
_When_(debugString != nullptr, _Pre_satisfies_(debugStringChars > 0)) size_t debugStringChars,
|
||||
_Inout_ bool* isNormalized) noexcept
|
||||
{
|
||||
if (g_pfnResultFromCaughtException)
|
||||
{
|
||||
try
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (const ResultException& exception)
|
||||
{
|
||||
*isNormalized = true;
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return exception.GetErrorCode();
|
||||
}
|
||||
catch (const winrt::hresult_error& exception)
|
||||
{
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return exception.to_abi();
|
||||
}
|
||||
catch (const std::bad_alloc& exception)
|
||||
{
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
catch (const std::out_of_range& exception)
|
||||
{
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return E_BOUNDS;
|
||||
}
|
||||
catch (const std::invalid_argument& exception)
|
||||
{
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
auto hr = RecognizeCaughtExceptionFromCallback(debugString, debugStringChars);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (const ResultException& exception)
|
||||
{
|
||||
*isNormalized = true;
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return exception.GetErrorCode();
|
||||
}
|
||||
catch (const winrt::hresult_error& exception)
|
||||
{
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return exception.to_abi();
|
||||
}
|
||||
catch (const std::bad_alloc& exception)
|
||||
{
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
catch (const std::out_of_range& exception)
|
||||
{
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return E_BOUNDS;
|
||||
}
|
||||
catch (const std::invalid_argument& exception)
|
||||
{
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
catch (const std::exception& exception)
|
||||
{
|
||||
MaybeGetExceptionString(exception, debugString, debugStringChars);
|
||||
return HRESULT_FROM_WIN32(ERROR_UNHANDLED_EXCEPTION);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Fall through to returning 'S_OK' below
|
||||
}
|
||||
}
|
||||
|
||||
// Tell the caller that we were unable to map the exception by succeeding...
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
namespace wil
|
||||
{
|
||||
inline std::int32_t __stdcall winrt_to_hresult(void* returnAddress) noexcept
|
||||
{
|
||||
// C++/WinRT only gives us the return address (caller), so pass along an empty 'DiagnosticsInfo' since we don't
|
||||
// have accurate file/line/etc. information
|
||||
return static_cast<std::int32_t>(details::ReportFailure_CaughtException<FailureType::Return>(__R_DIAGNOSTICS_RA(DiagnosticsInfo{}, returnAddress)));
|
||||
}
|
||||
|
||||
inline void WilInitialize_CppWinRT()
|
||||
{
|
||||
details::g_pfnResultFromCaughtException_CppWinRt = details::ResultFromCaughtException_CppWinRt;
|
||||
if constexpr (details::major_version_from_string(CPPWINRT_VERSION) >= 2)
|
||||
{
|
||||
WI_ASSERT(winrt_to_hresult_handler == nullptr);
|
||||
winrt_to_hresult_handler = winrt_to_hresult;
|
||||
}
|
||||
}
|
||||
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
#ifndef CPPWINRT_SUPPRESS_STATIC_INITIALIZERS
|
||||
WI_ODR_PRAGMA("CPPWINRT_SUPPRESS_STATIC_INITIALIZERS", "0")
|
||||
WI_HEADER_INITITALIZATION_FUNCTION(WilInitialize_CppWinRT, []
|
||||
{
|
||||
::wil::WilInitialize_CppWinRT();
|
||||
return 1;
|
||||
});
|
||||
#else
|
||||
WI_ODR_PRAGMA("CPPWINRT_SUPPRESS_STATIC_INITIALIZERS", "1")
|
||||
#endif
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
// Provides an overload of verify_hresult so that the WIL macros can recognize winrt::hresult as a valid "hresult" type.
|
||||
inline long verify_hresult(winrt::hresult hr) noexcept
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Provides versions of get_abi and put_abi for genericity that directly use HSTRING for convenience.
|
||||
template <typename T>
|
||||
auto get_abi(T const& object) noexcept
|
||||
{
|
||||
return winrt::get_abi(object);
|
||||
}
|
||||
|
||||
inline auto get_abi(winrt::hstring const& object) noexcept
|
||||
{
|
||||
return static_cast<HSTRING>(winrt::get_abi(object));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
auto put_abi(T& object) noexcept
|
||||
{
|
||||
return winrt::put_abi(object);
|
||||
}
|
||||
|
||||
inline auto put_abi(winrt::hstring& object) noexcept
|
||||
{
|
||||
return reinterpret_cast<HSTRING*>(winrt::put_abi(object));
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __WIL_CPPWINRT_INCLUDED
|
||||
963
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/filesystem.h
vendored
Normal file
@ -0,0 +1,963 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
#ifndef __WIL_FILESYSTEM_INCLUDED
|
||||
#define __WIL_FILESYSTEM_INCLUDED
|
||||
|
||||
#ifdef _KERNEL_MODE
|
||||
#error This header is not supported in kernel-mode.
|
||||
#endif
|
||||
|
||||
#include <new>
|
||||
#include <combaseapi.h> // Needed for CoTaskMemFree() used in output of some helpers.
|
||||
#include <winbase.h> // LocalAlloc
|
||||
#include <PathCch.h>
|
||||
#include "result.h"
|
||||
#include "win32_helpers.h"
|
||||
#include "resource.h"
|
||||
|
||||
namespace wil
|
||||
{
|
||||
//! Determines if a path is an extended length path that can be used to access paths longer than MAX_PATH.
|
||||
inline bool is_extended_length_path(_In_ PCWSTR path)
|
||||
{
|
||||
return wcsncmp(path, L"\\\\?\\", 4) == 0;
|
||||
}
|
||||
|
||||
//! Find the last segment of a path. Matches the behavior of shlwapi!PathFindFileNameW()
|
||||
//! note, does not support streams being specified like PathFindFileNameW(), is that a bug or a feature?
|
||||
inline PCWSTR find_last_path_segment(_In_ PCWSTR path)
|
||||
{
|
||||
auto const pathLength = wcslen(path);
|
||||
// If there is a trailing slash ignore that in the search.
|
||||
auto const limitedLength = ((pathLength > 0) && (path[pathLength - 1] == L'\\')) ? (pathLength - 1) : pathLength;
|
||||
|
||||
PCWSTR result;
|
||||
auto const offset = FindStringOrdinal(FIND_FROMEND, path, static_cast<int>(limitedLength), L"\\", 1, TRUE);
|
||||
if (offset == -1)
|
||||
{
|
||||
result = path + pathLength; // null terminator
|
||||
}
|
||||
else
|
||||
{
|
||||
result = path + offset + 1; // just past the slash
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//! Determine if the file name is one of the special "." or ".." names.
|
||||
inline bool path_is_dot_or_dotdot(_In_ PCWSTR fileName)
|
||||
{
|
||||
return ((fileName[0] == L'.') &&
|
||||
((fileName[1] == L'\0') || ((fileName[1] == L'.') && (fileName[2] == L'\0'))));
|
||||
}
|
||||
|
||||
//! Returns the drive number, if it has one. Returns true if there is a drive number, false otherwise. Supports regular and extended length paths.
|
||||
inline bool try_get_drive_letter_number(_In_ PCWSTR path, _Out_ int* driveNumber)
|
||||
{
|
||||
if (path[0] == L'\\' && path[1] == L'\\' && path[2] == L'?' && path[3] == L'\\')
|
||||
{
|
||||
path += 4;
|
||||
}
|
||||
if (path[0] && (path[1] == L':'))
|
||||
{
|
||||
if ((path[0] >= L'a') && (path[0] <= L'z'))
|
||||
{
|
||||
*driveNumber = path[0] - L'a';
|
||||
return true;
|
||||
}
|
||||
else if ((path[0] >= L'A') && (path[0] <= L'Z'))
|
||||
{
|
||||
*driveNumber = path[0] - L'A';
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*driveNumber = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
|
||||
// PathCch.h APIs are only in desktop API for now.
|
||||
|
||||
// Compute the substring in the input value that is the parent folder path.
|
||||
// returns:
|
||||
// true + parentPathLength - path has a parent starting at the beginning path and of parentPathLength length.
|
||||
// false, no parent path, the input is a root path.
|
||||
inline bool try_get_parent_path_range(_In_ PCWSTR path, _Out_ size_t* parentPathLength)
|
||||
{
|
||||
*parentPathLength = 0;
|
||||
bool hasParent = false;
|
||||
PCWSTR rootEnd;
|
||||
if (SUCCEEDED(PathCchSkipRoot(path, &rootEnd)) && (*rootEnd != L'\0'))
|
||||
{
|
||||
auto const lastSegment = find_last_path_segment(path);
|
||||
*parentPathLength = lastSegment - path;
|
||||
hasParent = (*parentPathLength != 0);
|
||||
}
|
||||
return hasParent;
|
||||
}
|
||||
|
||||
// Creates directories for the specified path, creating parent paths
|
||||
// as needed.
|
||||
inline HRESULT CreateDirectoryDeepNoThrow(PCWSTR path) WI_NOEXCEPT
|
||||
{
|
||||
if (::CreateDirectoryW(path, nullptr) == FALSE)
|
||||
{
|
||||
DWORD const lastError = ::GetLastError();
|
||||
if (lastError == ERROR_PATH_NOT_FOUND)
|
||||
{
|
||||
size_t parentLength;
|
||||
if (try_get_parent_path_range(path, &parentLength))
|
||||
{
|
||||
wistd::unique_ptr<wchar_t[]> parent(new (std::nothrow) wchar_t[parentLength + 1]);
|
||||
RETURN_IF_NULL_ALLOC(parent.get());
|
||||
RETURN_IF_FAILED(StringCchCopyNW(parent.get(), parentLength + 1, path, parentLength));
|
||||
CreateDirectoryDeepNoThrow(parent.get()); // recurs
|
||||
}
|
||||
RETURN_IF_WIN32_BOOL_FALSE(::CreateDirectoryW(path, nullptr));
|
||||
}
|
||||
else if (lastError != ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
RETURN_WIN32(lastError);
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
inline void CreateDirectoryDeep(PCWSTR path)
|
||||
{
|
||||
THROW_IF_FAILED(CreateDirectoryDeepNoThrow(path));
|
||||
}
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
|
||||
//! A strongly typed version of the Win32 API GetFullPathNameW.
|
||||
//! Return a path in an allocated buffer for handling long paths.
|
||||
//! Optionally return the pointer to the file name part.
|
||||
template <typename string_type, size_t stackBufferLength = 256>
|
||||
HRESULT GetFullPathNameW(PCWSTR file, string_type& path, _Outptr_opt_ PCWSTR* filePart = nullptr)
|
||||
{
|
||||
wil::assign_null_to_opt_param(filePart);
|
||||
const auto hr = AdaptFixedSizeToAllocatedResult<string_type, stackBufferLength>(path,
|
||||
[&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNull) -> HRESULT
|
||||
{
|
||||
// Note that GetFullPathNameW() is not limited to MAX_PATH
|
||||
// but it does take a fixed size buffer.
|
||||
*valueLengthNeededWithNull = ::GetFullPathNameW(file, static_cast<DWORD>(valueLength), value, nullptr);
|
||||
RETURN_LAST_ERROR_IF(*valueLengthNeededWithNull == 0);
|
||||
WI_ASSERT((*value != L'\0') == (*valueLengthNeededWithNull < valueLength));
|
||||
if (*valueLengthNeededWithNull < valueLength)
|
||||
{
|
||||
(*valueLengthNeededWithNull)++; // it fit, account for the null
|
||||
}
|
||||
return S_OK;
|
||||
});
|
||||
if (SUCCEEDED(hr) && filePart)
|
||||
{
|
||||
*filePart = wil::find_last_path_segment(details::string_maker<string_type>::get(path));
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
//! A strongly typed version of the Win32 API of GetFullPathNameW.
|
||||
//! Return a path in an allocated buffer for handling long paths.
|
||||
//! Optionally return the pointer to the file name part.
|
||||
template <typename string_type = wil::unique_cotaskmem_string, size_t stackBufferLength = 256>
|
||||
string_type GetFullPathNameW(PCWSTR file, _Outptr_opt_ PCWSTR* filePart = nullptr)
|
||||
{
|
||||
string_type result;
|
||||
THROW_IF_FAILED((GetFullPathNameW<string_type, stackBufferLength>(file, result, filePart)));
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
enum class RemoveDirectoryOptions
|
||||
{
|
||||
None = 0,
|
||||
KeepRootDirectory = 0x1
|
||||
};
|
||||
DEFINE_ENUM_FLAG_OPERATORS(RemoveDirectoryOptions);
|
||||
|
||||
namespace details
|
||||
{
|
||||
// Reparse points should not be traversed in most recursive walks of the file system,
|
||||
// unless allowed through the appropriate reparse tag.
|
||||
inline bool CanRecurseIntoDirectory(const FILE_ATTRIBUTE_TAG_INFO& info)
|
||||
{
|
||||
return (WI_IsFlagSet(info.FileAttributes, FILE_ATTRIBUTE_DIRECTORY) &&
|
||||
(WI_IsFlagClear(info.FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT) ||
|
||||
(IsReparseTagDirectory(info.ReparseTag) || (info.ReparseTag == IO_REPARSE_TAG_WCI))));
|
||||
}
|
||||
|
||||
// Retrieve a handle to a directory only if it is safe to recurse into.
|
||||
inline wil::unique_hfile TryCreateFileCanRecurseIntoDirectory(PCWSTR path, PWIN32_FIND_DATAW fileFindData)
|
||||
{
|
||||
wil::unique_hfile result(CreateFileW(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE,
|
||||
nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr));
|
||||
if (result)
|
||||
{
|
||||
FILE_ATTRIBUTE_TAG_INFO fati;
|
||||
if (GetFileInformationByHandleEx(result.get(), FileAttributeTagInfo, &fati, sizeof(fati)) &&
|
||||
CanRecurseIntoDirectory(fati))
|
||||
{
|
||||
if (fileFindData)
|
||||
{
|
||||
// Refresh the found file's data now that we have secured the directory from external manipulation.
|
||||
fileFindData->dwFileAttributes = fati.FileAttributes;
|
||||
fileFindData->dwReserved0 = fati.ReparseTag;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.reset();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// If inputPath is a non-normalized name be sure to pass an extended length form to ensure
|
||||
// it can be addressed and deleted.
|
||||
inline HRESULT RemoveDirectoryRecursiveNoThrow(PCWSTR inputPath, RemoveDirectoryOptions options = RemoveDirectoryOptions::None) WI_NOEXCEPT
|
||||
{
|
||||
wil::unique_hlocal_string path;
|
||||
PATHCCH_OPTIONS combineOptions = PATHCCH_NONE;
|
||||
|
||||
if (is_extended_length_path(inputPath))
|
||||
{
|
||||
path = wil::make_hlocal_string_nothrow(inputPath);
|
||||
RETURN_IF_NULL_ALLOC(path);
|
||||
// PathAllocCombine will convert extended length paths to regular paths if shorter than
|
||||
// MAX_PATH, avoid that behavior to provide access inputPath with non-normalized names.
|
||||
combineOptions = PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH;
|
||||
}
|
||||
else
|
||||
{
|
||||
// For regular paths normalize here to get consistent results when searching and deleting.
|
||||
RETURN_IF_FAILED(wil::GetFullPathNameW(inputPath, path));
|
||||
combineOptions = PATHCCH_ALLOW_LONG_PATHS;
|
||||
}
|
||||
|
||||
wil::unique_hlocal_string searchPath;
|
||||
RETURN_IF_FAILED(::PathAllocCombine(path.get(), L"*", combineOptions, &searchPath));
|
||||
|
||||
WIN32_FIND_DATAW fd;
|
||||
wil::unique_hfind findHandle(::FindFirstFileW(searchPath.get(), &fd));
|
||||
RETURN_LAST_ERROR_IF(!findHandle);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
// skip "." and ".."
|
||||
if (!(WI_IsFlagSet(fd.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY) && path_is_dot_or_dotdot(fd.cFileName)))
|
||||
{
|
||||
// Need to form an extended length path to provide the ability to delete paths > MAX_PATH
|
||||
// and files with non-normalized names (dots or spaces at the end).
|
||||
wil::unique_hlocal_string pathToDelete;
|
||||
RETURN_IF_FAILED(::PathAllocCombine(path.get(), fd.cFileName,
|
||||
PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH | PATHCCH_DO_NOT_NORMALIZE_SEGMENTS, &pathToDelete));
|
||||
if (WI_IsFlagSet(fd.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY))
|
||||
{
|
||||
// Get a handle to the directory to delete, preventing it from being replaced to prevent writes which could be used
|
||||
// to bypass permission checks, and verify that it is not a name surrogate (e.g. symlink, mount point, etc).
|
||||
wil::unique_hfile recursivelyDeletableDirectoryHandle = details::TryCreateFileCanRecurseIntoDirectory(pathToDelete.get(), &fd);
|
||||
if (recursivelyDeletableDirectoryHandle)
|
||||
{
|
||||
RemoveDirectoryOptions localOptions = options;
|
||||
RETURN_IF_FAILED(RemoveDirectoryRecursiveNoThrow(pathToDelete.get(), WI_ClearFlag(localOptions, RemoveDirectoryOptions::KeepRootDirectory)));
|
||||
}
|
||||
else if (WI_IsFlagSet(fd.dwFileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
|
||||
{
|
||||
// This is a directory reparse point that should not be recursed. Delete it without traversing into it.
|
||||
RETURN_IF_WIN32_BOOL_FALSE(::RemoveDirectoryW(pathToDelete.get()));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failed to grab a handle to the file or to read its attributes. This is not safe to recurse.
|
||||
RETURN_WIN32(::GetLastError());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// note: if pathToDelete is read-only this will fail, consider adding
|
||||
// RemoveDirectoryOptions::RemoveReadOnly to enable this behavior.
|
||||
RETURN_IF_WIN32_BOOL_FALSE(::DeleteFileW(pathToDelete.get()));
|
||||
}
|
||||
}
|
||||
|
||||
if (!::FindNextFileW(findHandle.get(), &fd))
|
||||
{
|
||||
auto const err = ::GetLastError();
|
||||
if (err == ERROR_NO_MORE_FILES)
|
||||
{
|
||||
break;
|
||||
}
|
||||
RETURN_WIN32(err);
|
||||
}
|
||||
}
|
||||
|
||||
if (WI_IsFlagClear(options, RemoveDirectoryOptions::KeepRootDirectory))
|
||||
{
|
||||
RETURN_IF_WIN32_BOOL_FALSE(::RemoveDirectoryW(path.get()));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
inline void RemoveDirectoryRecursive(PCWSTR path, RemoveDirectoryOptions options = RemoveDirectoryOptions::None)
|
||||
{
|
||||
THROW_IF_FAILED(RemoveDirectoryRecursiveNoThrow(path, options));
|
||||
}
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
|
||||
// Range based for that supports Win32 structures that use NextEntryOffset as the basis of traversing
|
||||
// a result buffer that contains data. This is used in the following FileIO calls:
|
||||
// FileStreamInfo, FILE_STREAM_INFO
|
||||
// FileIdBothDirectoryInfo, FILE_ID_BOTH_DIR_INFO
|
||||
// FileFullDirectoryInfo, FILE_FULL_DIR_INFO
|
||||
// FileIdExtdDirectoryInfo, FILE_ID_EXTD_DIR_INFO
|
||||
// ReadDirectoryChangesW, FILE_NOTIFY_INFORMATION
|
||||
|
||||
template <typename T>
|
||||
struct next_entry_offset_iterator
|
||||
{
|
||||
// Fulfill std::iterator_traits requirements
|
||||
using difference_type = ptrdiff_t;
|
||||
using value_type = T;
|
||||
using pointer = const T*;
|
||||
using reference = const T&;
|
||||
#ifdef _XUTILITY_
|
||||
using iterator_category = ::std::forward_iterator_tag;
|
||||
#endif
|
||||
|
||||
next_entry_offset_iterator(T *iterable = __nullptr) : current_(iterable) {}
|
||||
|
||||
// range based for requires operator!=, operator++ and operator* to do its work
|
||||
// on the type returned from begin() and end(), provide those here.
|
||||
bool operator!=(const next_entry_offset_iterator& other) const { return current_ != other.current_; }
|
||||
|
||||
next_entry_offset_iterator& operator++()
|
||||
{
|
||||
current_ = (current_->NextEntryOffset != 0) ?
|
||||
reinterpret_cast<T *>(reinterpret_cast<unsigned char*>(current_) + current_->NextEntryOffset) :
|
||||
__nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
next_entry_offset_iterator operator++(int)
|
||||
{
|
||||
auto copy = *this;
|
||||
++(*this);
|
||||
return copy;
|
||||
}
|
||||
|
||||
reference operator*() const WI_NOEXCEPT { return *current_; }
|
||||
pointer operator->() const WI_NOEXCEPT { return current_; }
|
||||
|
||||
next_entry_offset_iterator<T> begin() { return *this; }
|
||||
next_entry_offset_iterator<T> end() { return next_entry_offset_iterator<T>(); }
|
||||
|
||||
T* current_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
next_entry_offset_iterator<T> create_next_entry_offset_iterator(T* p)
|
||||
{
|
||||
return next_entry_offset_iterator<T>(p);
|
||||
}
|
||||
|
||||
#pragma region Folder Watcher
|
||||
// Example use in exception based code:
|
||||
// auto watcher = wil::make_folder_watcher(folder.Path().c_str(), true, wil::allChangeEvents, []()
|
||||
// {
|
||||
// // respond
|
||||
// });
|
||||
//
|
||||
// Example use in result code based code:
|
||||
// wil::unique_folder_watcher watcher;
|
||||
// THROW_IF_FAILED(watcher.create(folder, true, wil::allChangeEvents, []()
|
||||
// {
|
||||
// // respond
|
||||
// }));
|
||||
|
||||
enum class FolderChangeEvent : DWORD
|
||||
{
|
||||
ChangesLost = 0, // requies special handling, reset state as events were lost
|
||||
Added = FILE_ACTION_ADDED,
|
||||
Removed = FILE_ACTION_REMOVED,
|
||||
Modified = FILE_ACTION_MODIFIED,
|
||||
RenameOldName = FILE_ACTION_RENAMED_OLD_NAME,
|
||||
RenameNewName = FILE_ACTION_RENAMED_NEW_NAME,
|
||||
};
|
||||
|
||||
enum class FolderChangeEvents : DWORD
|
||||
{
|
||||
None = 0,
|
||||
FileName = FILE_NOTIFY_CHANGE_FILE_NAME,
|
||||
DirectoryName = FILE_NOTIFY_CHANGE_DIR_NAME,
|
||||
Attributes = FILE_NOTIFY_CHANGE_ATTRIBUTES,
|
||||
FileSize = FILE_NOTIFY_CHANGE_SIZE,
|
||||
LastWriteTime = FILE_NOTIFY_CHANGE_LAST_WRITE,
|
||||
Security = FILE_NOTIFY_CHANGE_SECURITY,
|
||||
All = FILE_NOTIFY_CHANGE_FILE_NAME |
|
||||
FILE_NOTIFY_CHANGE_DIR_NAME |
|
||||
FILE_NOTIFY_CHANGE_ATTRIBUTES |
|
||||
FILE_NOTIFY_CHANGE_SIZE |
|
||||
FILE_NOTIFY_CHANGE_LAST_WRITE |
|
||||
FILE_NOTIFY_CHANGE_SECURITY
|
||||
};
|
||||
DEFINE_ENUM_FLAG_OPERATORS(FolderChangeEvents);
|
||||
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
struct folder_watcher_state
|
||||
{
|
||||
folder_watcher_state(wistd::function<void()> &&callback) : m_callback(wistd::move(callback))
|
||||
{
|
||||
}
|
||||
wistd::function<void()> m_callback;
|
||||
// Order is important, need to close the thread pool wait before the change handle.
|
||||
unique_hfind_change m_findChangeHandle;
|
||||
unique_threadpool_wait m_threadPoolWait;
|
||||
};
|
||||
|
||||
inline void delete_folder_watcher_state(_In_opt_ folder_watcher_state *storage) { delete storage; }
|
||||
|
||||
typedef resource_policy<folder_watcher_state *, decltype(&details::delete_folder_watcher_state),
|
||||
details::delete_folder_watcher_state, details::pointer_access_none> folder_watcher_state_resource_policy;
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
template <typename storage_t, typename err_policy = err_exception_policy>
|
||||
class folder_watcher_t : public storage_t
|
||||
{
|
||||
public:
|
||||
// forward all base class constructors...
|
||||
template <typename... args_t>
|
||||
explicit folder_watcher_t(args_t&&... args) WI_NOEXCEPT : storage_t(wistd::forward<args_t>(args)...) {}
|
||||
|
||||
// HRESULT or void error handling...
|
||||
typedef typename err_policy::result result;
|
||||
|
||||
// Exception-based constructors
|
||||
folder_watcher_t(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter, wistd::function<void()> &&callback)
|
||||
{
|
||||
static_assert(wistd::is_same<void, result>::value, "this constructor requires exceptions; use the create method");
|
||||
create(folderToWatch, isRecursive, filter, wistd::move(callback));
|
||||
}
|
||||
|
||||
result create(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter, wistd::function<void()> &&callback)
|
||||
{
|
||||
return err_policy::HResult(create_common(folderToWatch, isRecursive, filter, wistd::move(callback)));
|
||||
}
|
||||
private:
|
||||
// Factored into a standalone function to support Clang which does not support conversion of stateless lambdas
|
||||
// to __stdcall
|
||||
static void __stdcall callback(PTP_CALLBACK_INSTANCE /*Instance*/, void *context, TP_WAIT *pThreadPoolWait, TP_WAIT_RESULT /*result*/)
|
||||
{
|
||||
auto watcherState = static_cast<details::folder_watcher_state *>(context);
|
||||
watcherState->m_callback();
|
||||
|
||||
// Rearm the wait. Should not fail with valid parameters.
|
||||
FindNextChangeNotification(watcherState->m_findChangeHandle.get());
|
||||
SetThreadpoolWait(pThreadPoolWait, watcherState->m_findChangeHandle.get(), __nullptr);
|
||||
}
|
||||
|
||||
// This function exists to avoid template expansion of this code based on err_policy.
|
||||
HRESULT create_common(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter, wistd::function<void()> &&callback)
|
||||
{
|
||||
wistd::unique_ptr<details::folder_watcher_state> watcherState(new(std::nothrow) details::folder_watcher_state(wistd::move(callback)));
|
||||
RETURN_IF_NULL_ALLOC(watcherState);
|
||||
|
||||
watcherState->m_findChangeHandle.reset(FindFirstChangeNotificationW(folderToWatch, isRecursive, static_cast<DWORD>(filter)));
|
||||
RETURN_LAST_ERROR_IF(!watcherState->m_findChangeHandle);
|
||||
|
||||
watcherState->m_threadPoolWait.reset(CreateThreadpoolWait(&folder_watcher_t::callback, watcherState.get(), __nullptr));
|
||||
RETURN_LAST_ERROR_IF(!watcherState->m_threadPoolWait);
|
||||
this->reset(watcherState.release()); // no more failures after this, pass ownership
|
||||
SetThreadpoolWait(this->get()->m_threadPoolWait.get(), this->get()->m_findChangeHandle.get(), __nullptr);
|
||||
return S_OK;
|
||||
}
|
||||
};
|
||||
|
||||
typedef unique_any_t<folder_watcher_t<details::unique_storage<details::folder_watcher_state_resource_policy>, err_returncode_policy>> unique_folder_watcher_nothrow;
|
||||
|
||||
inline unique_folder_watcher_nothrow make_folder_watcher_nothrow(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter, wistd::function<void()> &&callback) WI_NOEXCEPT
|
||||
{
|
||||
unique_folder_watcher_nothrow watcher;
|
||||
watcher.create(folderToWatch, isRecursive, filter, wistd::move(callback));
|
||||
return watcher; // caller must test for success using if (watcher)
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
typedef unique_any_t<folder_watcher_t<details::unique_storage<details::folder_watcher_state_resource_policy>, err_exception_policy>> unique_folder_watcher;
|
||||
|
||||
inline unique_folder_watcher make_folder_watcher(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter, wistd::function<void()> &&callback)
|
||||
{
|
||||
return unique_folder_watcher(folderToWatch, isRecursive, filter, wistd::move(callback));
|
||||
}
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Folder Reader
|
||||
|
||||
// Example use for throwing:
|
||||
// auto reader = wil::make_folder_change_reader(folder.Path().c_str(), true, wil::FolderChangeEvents::All,
|
||||
// [](wil::FolderChangeEvent event, PCWSTR fileName)
|
||||
// {
|
||||
// switch (event)
|
||||
// {
|
||||
// case wil::FolderChangeEvent::ChangesLost: break;
|
||||
// case wil::FolderChangeEvent::Added: break;
|
||||
// case wil::FolderChangeEvent::Removed: break;
|
||||
// case wil::FolderChangeEvent::Modified: break;
|
||||
// case wil::FolderChangeEvent::RenamedOldName: break;
|
||||
// case wil::FolderChangeEvent::RenamedNewName: break;
|
||||
// });
|
||||
//
|
||||
// Example use for non throwing:
|
||||
// wil::unique_folder_change_reader_nothrow reader;
|
||||
// THROW_IF_FAILED(reader.create(folder, true, wil::FolderChangeEvents::All,
|
||||
// [](wil::FolderChangeEvent event, PCWSTR fileName)
|
||||
// {
|
||||
// // handle changes
|
||||
// }));
|
||||
//
|
||||
|
||||
// @cond
|
||||
namespace details
|
||||
{
|
||||
struct folder_change_reader_state
|
||||
{
|
||||
folder_change_reader_state(bool isRecursive, FolderChangeEvents filter, wistd::function<void(FolderChangeEvent, PCWSTR)> &&callback)
|
||||
: m_callback(wistd::move(callback)), m_isRecursive(isRecursive), m_filter(filter)
|
||||
{
|
||||
}
|
||||
|
||||
~folder_change_reader_state()
|
||||
{
|
||||
if (m_tpIo != __nullptr)
|
||||
{
|
||||
TP_IO *tpIo = m_tpIo;
|
||||
|
||||
// Indicate to the callback function that this object is being torn
|
||||
// down.
|
||||
|
||||
{
|
||||
auto autoLock = m_cancelLock.lock_exclusive();
|
||||
m_tpIo = __nullptr;
|
||||
}
|
||||
|
||||
// Cancel IO to terminate the file system monitoring operation.
|
||||
|
||||
if (m_folderHandle)
|
||||
{
|
||||
CancelIoEx(m_folderHandle.get(), &m_overlapped);
|
||||
}
|
||||
|
||||
// Wait for callbacks to complete.
|
||||
//
|
||||
// N.B. This is a blocking call and must not be made within a
|
||||
// callback or within a lock which is taken inside the
|
||||
// callback.
|
||||
|
||||
WaitForThreadpoolIoCallbacks(tpIo, TRUE);
|
||||
CloseThreadpoolIo(tpIo);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT StartIo()
|
||||
{
|
||||
// Unfortunately we have to handle ref-counting of IOs on behalf of the
|
||||
// thread pool.
|
||||
StartThreadpoolIo(m_tpIo);
|
||||
HRESULT hr = ReadDirectoryChangesW(m_folderHandle.get(), m_readBuffer, sizeof(m_readBuffer),
|
||||
m_isRecursive, static_cast<DWORD>(m_filter), __nullptr, &m_overlapped, __nullptr) ?
|
||||
S_OK : HRESULT_FROM_WIN32(::GetLastError());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// This operation does not have the usual semantic of returning
|
||||
// ERROR_IO_PENDING.
|
||||
// WI_ASSERT(hr != HRESULT_FROM_WIN32(ERROR_IO_PENDING));
|
||||
|
||||
// If the operation failed for whatever reason, ensure the TP
|
||||
// ref counts are accurate.
|
||||
|
||||
CancelThreadpoolIo(m_tpIo);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
// void (wil::FolderChangeEvent event, PCWSTR fileName)
|
||||
wistd::function<void(FolderChangeEvent, PCWSTR)> m_callback;
|
||||
unique_handle m_folderHandle;
|
||||
BOOL m_isRecursive = FALSE;
|
||||
FolderChangeEvents m_filter = FolderChangeEvents::None;
|
||||
OVERLAPPED m_overlapped{};
|
||||
TP_IO *m_tpIo = __nullptr;
|
||||
srwlock m_cancelLock;
|
||||
char m_readBuffer[4096]; // Consider alternative buffer sizes. With 512 byte buffer i was not able to observe overflow.
|
||||
};
|
||||
|
||||
inline void delete_folder_change_reader_state(_In_opt_ folder_change_reader_state *storage) { delete storage; }
|
||||
|
||||
typedef resource_policy<folder_change_reader_state *, decltype(&details::delete_folder_change_reader_state),
|
||||
details::delete_folder_change_reader_state, details::pointer_access_none> folder_change_reader_state_resource_policy;
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
template <typename storage_t, typename err_policy = err_exception_policy>
|
||||
class folder_change_reader_t : public storage_t
|
||||
{
|
||||
public:
|
||||
// forward all base class constructors...
|
||||
template <typename... args_t>
|
||||
explicit folder_change_reader_t(args_t&&... args) WI_NOEXCEPT : storage_t(wistd::forward<args_t>(args)...) {}
|
||||
|
||||
// HRESULT or void error handling...
|
||||
typedef typename err_policy::result result;
|
||||
|
||||
// Exception-based constructors
|
||||
folder_change_reader_t(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter, wistd::function<void(FolderChangeEvent, PCWSTR)> &&callback)
|
||||
{
|
||||
static_assert(wistd::is_same<void, result>::value, "this constructor requires exceptions; use the create method");
|
||||
create(folderToWatch, isRecursive, filter, wistd::move(callback));
|
||||
}
|
||||
|
||||
result create(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter, wistd::function<void(FolderChangeEvent, PCWSTR)> &&callback)
|
||||
{
|
||||
return err_policy::HResult(create_common(folderToWatch, isRecursive, filter, wistd::move(callback)));
|
||||
}
|
||||
|
||||
wil::unique_hfile& folder_handle() { return this->get()->m_folderHandle; }
|
||||
|
||||
private:
|
||||
// Factored into a standalone function to support Clang which does not support conversion of stateless lambdas
|
||||
// to __stdcall
|
||||
static void __stdcall callback(PTP_CALLBACK_INSTANCE /* Instance */, void *context, void * /*overlapped*/,
|
||||
ULONG result, ULONG_PTR /* BytesTransferred */, TP_IO * /* Io */)
|
||||
{
|
||||
auto readerState = static_cast<details::folder_change_reader_state *>(context);
|
||||
// WI_ASSERT(overlapped == &readerState->m_overlapped);
|
||||
|
||||
bool requeue = true;
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
for (auto const& info : create_next_entry_offset_iterator(reinterpret_cast<FILE_NOTIFY_INFORMATION *>(readerState->m_readBuffer)))
|
||||
{
|
||||
wchar_t realtiveFileName[MAX_PATH];
|
||||
StringCchCopyNW(realtiveFileName, ARRAYSIZE(realtiveFileName), info.FileName, info.FileNameLength / sizeof(info.FileName[0]));
|
||||
|
||||
readerState->m_callback(static_cast<FolderChangeEvent>(info.Action), realtiveFileName);
|
||||
}
|
||||
}
|
||||
else if (result == ERROR_NOTIFY_ENUM_DIR)
|
||||
{
|
||||
readerState->m_callback(FolderChangeEvent::ChangesLost, __nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
requeue = false;
|
||||
}
|
||||
|
||||
if (requeue)
|
||||
{
|
||||
// If the lock is held non-shared or the TP IO is nullptr, this
|
||||
// structure is being torn down. Otherwise, monitor for further
|
||||
// changes.
|
||||
auto autoLock = readerState->m_cancelLock.try_lock_shared();
|
||||
if (autoLock && readerState->m_tpIo)
|
||||
{
|
||||
readerState->StartIo(); // ignoring failure here
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This function exists to avoid template expansion of this code based on err_policy.
|
||||
HRESULT create_common(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter, wistd::function<void(FolderChangeEvent, PCWSTR)> &&callback)
|
||||
{
|
||||
wistd::unique_ptr<details::folder_change_reader_state> readerState(new(std::nothrow) details::folder_change_reader_state(
|
||||
isRecursive, filter, wistd::move(callback)));
|
||||
RETURN_IF_NULL_ALLOC(readerState);
|
||||
|
||||
readerState->m_folderHandle.reset(CreateFileW(folderToWatch,
|
||||
FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
|
||||
__nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, __nullptr));
|
||||
RETURN_LAST_ERROR_IF(!readerState->m_folderHandle);
|
||||
|
||||
readerState->m_tpIo = CreateThreadpoolIo(readerState->m_folderHandle.get(), &folder_change_reader_t::callback, readerState.get(), __nullptr);
|
||||
RETURN_LAST_ERROR_IF_NULL(readerState->m_tpIo);
|
||||
RETURN_IF_FAILED(readerState->StartIo());
|
||||
this->reset(readerState.release());
|
||||
return S_OK;
|
||||
}
|
||||
};
|
||||
|
||||
typedef unique_any_t<folder_change_reader_t<details::unique_storage<details::folder_change_reader_state_resource_policy>, err_returncode_policy>> unique_folder_change_reader_nothrow;
|
||||
|
||||
inline unique_folder_change_reader_nothrow make_folder_change_reader_nothrow(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter,
|
||||
wistd::function<void(FolderChangeEvent, PCWSTR)> &&callback) WI_NOEXCEPT
|
||||
{
|
||||
unique_folder_change_reader_nothrow watcher;
|
||||
watcher.create(folderToWatch, isRecursive, filter, wistd::move(callback));
|
||||
return watcher; // caller must test for success using if (watcher)
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
typedef unique_any_t<folder_change_reader_t<details::unique_storage<details::folder_change_reader_state_resource_policy>, err_exception_policy>> unique_folder_change_reader;
|
||||
|
||||
inline unique_folder_change_reader make_folder_change_reader(PCWSTR folderToWatch, bool isRecursive, FolderChangeEvents filter,
|
||||
wistd::function<void(FolderChangeEvent, PCWSTR)> &&callback)
|
||||
{
|
||||
return unique_folder_change_reader(folderToWatch, isRecursive, filter, wistd::move(callback));
|
||||
}
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
#pragma endregion
|
||||
|
||||
//! Dos and VolumeGuid paths are always extended length paths with the \\?\ prefix.
|
||||
enum class VolumePrefix
|
||||
{
|
||||
Dos = VOLUME_NAME_DOS, // Extended Dos Device path form, e.g. \\?\C:\Users\Chris\AppData\Local\Temp\wil8C31.tmp
|
||||
VolumeGuid = VOLUME_NAME_GUID, // \\?\Volume{588fb606-b95b-4eae-b3cb-1e49861aaf18}\Users\Chris\AppData\Local\Temp\wil8C31.tmp
|
||||
// The following are special paths which can't be used with Win32 APIs, but are useful in other scenarios.
|
||||
None = VOLUME_NAME_NONE, // Path without the volume root, e.g. \Users\Chris\AppData\Local\Temp\wil8C31.tmp
|
||||
NtObjectName = VOLUME_NAME_NT, // Unique name used by Object Manager, e.g. \Device\HarddiskVolume4\Users\Chris\AppData\Local\Temp\wil8C31.tmp
|
||||
};
|
||||
enum class PathOptions
|
||||
{
|
||||
Normalized = FILE_NAME_NORMALIZED,
|
||||
Opened = FILE_NAME_OPENED,
|
||||
};
|
||||
DEFINE_ENUM_FLAG_OPERATORS(PathOptions);
|
||||
|
||||
/** A strongly typed version of the Win32 API GetFinalPathNameByHandleW.
|
||||
Get the full path name in different forms
|
||||
Use this instead + VolumePrefix::None instead of GetFileInformationByHandleEx(FileNameInfo) to
|
||||
get that path form. */
|
||||
template <typename string_type, size_t stackBufferLength = 256>
|
||||
HRESULT GetFinalPathNameByHandleW(HANDLE fileHandle, string_type& path,
|
||||
wil::VolumePrefix volumePrefix = wil::VolumePrefix::Dos, wil::PathOptions options = wil::PathOptions::Normalized)
|
||||
{
|
||||
return AdaptFixedSizeToAllocatedResult<string_type, stackBufferLength>(path,
|
||||
[&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNull) -> HRESULT
|
||||
{
|
||||
*valueLengthNeededWithNull = ::GetFinalPathNameByHandleW(fileHandle, value, static_cast<DWORD>(valueLength),
|
||||
static_cast<DWORD>(volumePrefix) | static_cast<DWORD>(options));
|
||||
RETURN_LAST_ERROR_IF(*valueLengthNeededWithNull == 0);
|
||||
WI_ASSERT((*value != L'\0') == (*valueLengthNeededWithNull < valueLength));
|
||||
if (*valueLengthNeededWithNull < valueLength)
|
||||
{
|
||||
(*valueLengthNeededWithNull)++; // it fit, account for the null
|
||||
}
|
||||
return S_OK;
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
/** A strongly typed version of the Win32 API GetFinalPathNameByHandleW.
|
||||
Get the full path name in different forms. Use this + VolumePrefix::None
|
||||
instead of GetFileInformationByHandleEx(FileNameInfo) to get that path form. */
|
||||
template <typename string_type = wil::unique_cotaskmem_string, size_t stackBufferLength = 256>
|
||||
string_type GetFinalPathNameByHandleW(HANDLE fileHandle,
|
||||
wil::VolumePrefix volumePrefix = wil::VolumePrefix::Dos, wil::PathOptions options = wil::PathOptions::Normalized)
|
||||
{
|
||||
string_type result;
|
||||
THROW_IF_FAILED((GetFinalPathNameByHandleW<string_type, stackBufferLength>(fileHandle, result, volumePrefix, options)));
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
//! A strongly typed version of the Win32 API of GetCurrentDirectoryW.
|
||||
//! Return a path in an allocated buffer for handling long paths.
|
||||
template <typename string_type, size_t stackBufferLength = 256>
|
||||
HRESULT GetCurrentDirectoryW(string_type& path)
|
||||
{
|
||||
return AdaptFixedSizeToAllocatedResult<string_type, stackBufferLength>(path,
|
||||
[&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNull) -> HRESULT
|
||||
{
|
||||
*valueLengthNeededWithNull = ::GetCurrentDirectoryW(static_cast<DWORD>(valueLength), value);
|
||||
RETURN_LAST_ERROR_IF(*valueLengthNeededWithNull == 0);
|
||||
WI_ASSERT((*value != L'\0') == (*valueLengthNeededWithNull < valueLength));
|
||||
if (*valueLengthNeededWithNull < valueLength)
|
||||
{
|
||||
(*valueLengthNeededWithNull)++; // it fit, account for the null
|
||||
}
|
||||
return S_OK;
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
//! A strongly typed version of the Win32 API of GetCurrentDirectoryW.
|
||||
//! Return a path in an allocated buffer for handling long paths.
|
||||
template <typename string_type = wil::unique_cotaskmem_string, size_t stackBufferLength = 256>
|
||||
string_type GetCurrentDirectoryW()
|
||||
{
|
||||
string_type result;
|
||||
THROW_IF_FAILED((GetCurrentDirectoryW<string_type, stackBufferLength>(result)));
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: add support for these and other similar APIs.
|
||||
// GetShortPathNameW()
|
||||
// GetLongPathNameW()
|
||||
// GetWindowsDirectory()
|
||||
// GetTempDirectory()
|
||||
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
template <FILE_INFO_BY_HANDLE_CLASS infoClass> struct MapInfoClassToInfoStruct; // failure to map is a usage error caught by the compiler
|
||||
#define MAP_INFOCLASS_TO_STRUCT(InfoClass, InfoStruct, IsFixed, Extra) \
|
||||
template <> struct MapInfoClassToInfoStruct<InfoClass> \
|
||||
{ \
|
||||
typedef InfoStruct type; \
|
||||
static bool const isFixed = IsFixed; \
|
||||
static size_t const extraSize = Extra; \
|
||||
};
|
||||
|
||||
MAP_INFOCLASS_TO_STRUCT(FileBasicInfo, FILE_BASIC_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileStandardInfo, FILE_STANDARD_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileNameInfo, FILE_NAME_INFO, false, 32);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileRenameInfo, FILE_RENAME_INFO, false, 32);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileDispositionInfo, FILE_DISPOSITION_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileAllocationInfo, FILE_ALLOCATION_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileEndOfFileInfo, FILE_END_OF_FILE_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileStreamInfo, FILE_STREAM_INFO, false, 32);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileCompressionInfo, FILE_COMPRESSION_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileAttributeTagInfo, FILE_ATTRIBUTE_TAG_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileIdBothDirectoryInfo, FILE_ID_BOTH_DIR_INFO, false, 4096);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileIdBothDirectoryRestartInfo, FILE_ID_BOTH_DIR_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileIoPriorityHintInfo, FILE_IO_PRIORITY_HINT_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileRemoteProtocolInfo, FILE_REMOTE_PROTOCOL_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileFullDirectoryInfo, FILE_FULL_DIR_INFO, false, 4096);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileFullDirectoryRestartInfo, FILE_FULL_DIR_INFO, true, 0);
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
|
||||
MAP_INFOCLASS_TO_STRUCT(FileStorageInfo, FILE_STORAGE_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileAlignmentInfo, FILE_ALIGNMENT_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileIdInfo, FILE_ID_INFO, true, 0);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileIdExtdDirectoryInfo, FILE_ID_EXTD_DIR_INFO, false, 4096);
|
||||
MAP_INFOCLASS_TO_STRUCT(FileIdExtdDirectoryRestartInfo, FILE_ID_EXTD_DIR_INFO, true, 0);
|
||||
#endif
|
||||
|
||||
// Type unsafe version used in the implementation to avoid template bloat.
|
||||
inline HRESULT GetFileInfo(HANDLE fileHandle, FILE_INFO_BY_HANDLE_CLASS infoClass, size_t allocationSize,
|
||||
_Outptr_result_nullonfailure_ void **result)
|
||||
{
|
||||
*result = nullptr;
|
||||
|
||||
wistd::unique_ptr<char[]> resultHolder(new(std::nothrow) char[allocationSize]);
|
||||
RETURN_IF_NULL_ALLOC(resultHolder);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (GetFileInformationByHandleEx(fileHandle, infoClass, resultHolder.get(), static_cast<DWORD>(allocationSize)))
|
||||
{
|
||||
*result = resultHolder.release();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD const lastError = ::GetLastError();
|
||||
if (lastError == ERROR_MORE_DATA)
|
||||
{
|
||||
allocationSize *= 2;
|
||||
resultHolder.reset(new(std::nothrow) char[allocationSize]);
|
||||
RETURN_IF_NULL_ALLOC(resultHolder);
|
||||
}
|
||||
else if (lastError == ERROR_NO_MORE_FILES) // for folder enumeration cases
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (lastError == ERROR_INVALID_PARAMETER) // operation not supported by file system
|
||||
{
|
||||
return HRESULT_FROM_WIN32(lastError);
|
||||
}
|
||||
else
|
||||
{
|
||||
RETURN_WIN32(lastError);
|
||||
}
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
/** Get file information for a variable sized structure, returns an HRESULT.
|
||||
~~~
|
||||
wistd::unique_ptr<FILE_NAME_INFO> fileNameInfo;
|
||||
RETURN_IF_FAILED(GetFileInfoNoThrow<FileNameInfo>(fileHandle, fileNameInfo));
|
||||
~~~
|
||||
*/
|
||||
template <FILE_INFO_BY_HANDLE_CLASS infoClass, typename wistd::enable_if<!details::MapInfoClassToInfoStruct<infoClass>::isFixed, int>::type = 0>
|
||||
HRESULT GetFileInfoNoThrow(HANDLE fileHandle, wistd::unique_ptr<typename details::MapInfoClassToInfoStruct<infoClass>::type> &result) WI_NOEXCEPT
|
||||
{
|
||||
void *rawResult;
|
||||
HRESULT hr = details::GetFileInfo(fileHandle, infoClass,
|
||||
sizeof(typename details::MapInfoClassToInfoStruct<infoClass>::type) + details::MapInfoClassToInfoStruct<infoClass>::extraSize,
|
||||
&rawResult);
|
||||
result.reset(static_cast<typename details::MapInfoClassToInfoStruct<infoClass>::type*>(rawResult));
|
||||
RETURN_HR_IF_EXPECTED(hr, hr == E_INVALIDARG); // operation not supported by file system
|
||||
RETURN_IF_FAILED(hr);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/** Get file information for a fixed sized structure, returns an HRESULT.
|
||||
~~~
|
||||
FILE_BASIC_INFO fileBasicInfo;
|
||||
RETURN_IF_FAILED(GetFileInfoNoThrow<FileBasicInfo>(fileHandle, &fileBasicInfo));
|
||||
~~~
|
||||
*/
|
||||
template <FILE_INFO_BY_HANDLE_CLASS infoClass, typename wistd::enable_if<details::MapInfoClassToInfoStruct<infoClass>::isFixed, int>::type = 0>
|
||||
HRESULT GetFileInfoNoThrow(HANDLE fileHandle, _Out_ typename details::MapInfoClassToInfoStruct<infoClass>::type *result) WI_NOEXCEPT
|
||||
{
|
||||
const HRESULT hr = GetFileInformationByHandleEx(fileHandle, infoClass, result, sizeof(*result)) ?
|
||||
S_OK : HRESULT_FROM_WIN32(::GetLastError());
|
||||
RETURN_HR_IF_EXPECTED(hr, hr == E_INVALIDARG); // operation not supported by file system
|
||||
RETURN_IF_FAILED(hr);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifdef _CPPUNWIND
|
||||
/** Get file information for a fixed sized structure, throws on failure.
|
||||
~~~
|
||||
auto fileBasicInfo = GetFileInfo<FileBasicInfo>(fileHandle);
|
||||
~~~
|
||||
*/
|
||||
template <FILE_INFO_BY_HANDLE_CLASS infoClass, typename wistd::enable_if<details::MapInfoClassToInfoStruct<infoClass>::isFixed, int>::type = 0>
|
||||
typename details::MapInfoClassToInfoStruct<infoClass>::type GetFileInfo(HANDLE fileHandle)
|
||||
{
|
||||
typename details::MapInfoClassToInfoStruct<infoClass>::type result;
|
||||
THROW_IF_FAILED(GetFileInfoNoThrow<infoClass>(fileHandle, &result));
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Get file information for a variable sized structure, throws on failure.
|
||||
~~~
|
||||
auto fileBasicInfo = GetFileInfo<FileNameInfo>(fileHandle);
|
||||
~~~
|
||||
*/
|
||||
template <FILE_INFO_BY_HANDLE_CLASS infoClass, typename wistd::enable_if<!details::MapInfoClassToInfoStruct<infoClass>::isFixed, int>::type = 0>
|
||||
wistd::unique_ptr<typename details::MapInfoClassToInfoStruct<infoClass>::type> GetFileInfo(HANDLE fileHandle)
|
||||
{
|
||||
wistd::unique_ptr<typename details::MapInfoClassToInfoStruct<infoClass>::type> result;
|
||||
THROW_IF_FAILED(GetFileInfoNoThrow<infoClass>(fileHandle, result));
|
||||
return result;
|
||||
}
|
||||
#endif // _CPPUNWIND
|
||||
#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
}
|
||||
|
||||
#endif // __WIL_FILESYSTEM_INCLUDED
|
||||
277
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/registry.h
vendored
Normal file
@ -0,0 +1,277 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
#ifndef __WIL_REGISTRY_INCLUDED
|
||||
#define __WIL_REGISTRY_INCLUDED
|
||||
|
||||
#ifdef _KERNEL_MODE
|
||||
#error This header is not supported in kernel-mode.
|
||||
#endif
|
||||
|
||||
#include <winreg.h>
|
||||
#include <new.h> // new(std::nothrow)
|
||||
#include "resource.h" // unique_hkey
|
||||
|
||||
namespace wil
|
||||
{
|
||||
//! The key name includes the absolute path of the key in the registry, always starting at a
|
||||
//! base key, for example, HKEY_LOCAL_MACHINE.
|
||||
size_t const max_registry_key_name_length = 255;
|
||||
|
||||
//! The maximum number of characters allowed in a registry value's name.
|
||||
size_t const max_registry_value_name_length = 16383;
|
||||
|
||||
// unique_registry_watcher/unique_registry_watcher_nothrow/unique_registry_watcher_failfast
|
||||
// These classes make it easy to execute a provided function when a
|
||||
// registry key changes (optionally recursively). Specify the key
|
||||
// either as a root key + path, or an open registry handle as wil::unique_hkey
|
||||
// or a raw HKEY value (that will be duplicated).
|
||||
//
|
||||
// Example use with exceptions base error handling:
|
||||
// auto watcher = wil::make_registry_watcher(HKEY_CURRENT_USER, L"Software\\MyApp", true, wil::RegistryChangeKind changeKind[]
|
||||
// {
|
||||
// if (changeKind == RegistryChangeKind::Delete)
|
||||
// {
|
||||
// watcher.reset();
|
||||
// }
|
||||
// // invalidate cached registry data here
|
||||
// });
|
||||
//
|
||||
// Example use with error code base error handling:
|
||||
// auto watcher = wil::make_registry_watcher_nothrow(HKEY_CURRENT_USER, L"Software\\MyApp", true, wil::RegistryChangeKind[]
|
||||
// {
|
||||
// // invalidate cached registry data here
|
||||
// });
|
||||
// RETURN_IF_NULL_ALLOC(watcher);
|
||||
|
||||
enum class RegistryChangeKind
|
||||
{
|
||||
Modify = 0,
|
||||
Delete = 1,
|
||||
};
|
||||
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
struct registry_watcher_state
|
||||
{
|
||||
registry_watcher_state(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
: m_callback(wistd::move(callback)), m_keyToWatch(wistd::move(keyToWatch)), m_isRecursive(isRecursive)
|
||||
{
|
||||
}
|
||||
wistd::function<void(RegistryChangeKind)> m_callback;
|
||||
unique_hkey m_keyToWatch;
|
||||
unique_event_nothrow m_eventHandle;
|
||||
|
||||
// While not strictly needed since this is ref counted the thread pool wait
|
||||
// should be last to ensure that the other members are valid
|
||||
// when it is destructed as it will reference them.
|
||||
unique_threadpool_wait m_threadPoolWait;
|
||||
bool m_isRecursive;
|
||||
|
||||
volatile long m_refCount = 1;
|
||||
srwlock m_lock;
|
||||
|
||||
// Returns true if the refcount can be increased from a non zero value,
|
||||
// false it was zero impling that the object is in or on the way to the destructor.
|
||||
// In this case ReleaseFromCallback() should not be called.
|
||||
bool TryAddRef()
|
||||
{
|
||||
return ::InterlockedIncrement(&m_refCount) > 1;
|
||||
}
|
||||
|
||||
void Release()
|
||||
{
|
||||
auto lock = m_lock.lock_exclusive();
|
||||
if (0 == ::InterlockedDecrement(&m_refCount))
|
||||
{
|
||||
lock.reset(); // leave the lock before deleting it.
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
void ReleaseFromCallback(bool rearm)
|
||||
{
|
||||
auto lock = m_lock.lock_exclusive();
|
||||
if (0 == ::InterlockedDecrement(&m_refCount))
|
||||
{
|
||||
// Destroy the thread pool wait now to avoid the wait that would occur in the
|
||||
// destructor. That wait would cause a deadlock since we are doing this from the callback.
|
||||
::CloseThreadpoolWait(m_threadPoolWait.release());
|
||||
lock.reset(); // leave the lock before deleting it.
|
||||
delete this;
|
||||
// Sleep(1); // Enable for testing to find use after free bugs.
|
||||
}
|
||||
else if (rearm)
|
||||
{
|
||||
::SetThreadpoolWait(m_threadPoolWait.get(), m_eventHandle.get(), nullptr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline void delete_registry_watcher_state(_In_opt_ registry_watcher_state *watcherStorage) { watcherStorage->Release(); }
|
||||
|
||||
typedef resource_policy<registry_watcher_state *, decltype(&details::delete_registry_watcher_state),
|
||||
details::delete_registry_watcher_state, details::pointer_access_none> registry_watcher_state_resource_policy;
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
template <typename storage_t, typename err_policy = err_exception_policy>
|
||||
class registry_watcher_t : public storage_t
|
||||
{
|
||||
public:
|
||||
// forward all base class constructors...
|
||||
template <typename... args_t>
|
||||
explicit registry_watcher_t(args_t&&... args) WI_NOEXCEPT : storage_t(wistd::forward<args_t>(args)...) {}
|
||||
|
||||
// HRESULT or void error handling...
|
||||
typedef typename err_policy::result result;
|
||||
|
||||
// Exception-based constructors
|
||||
registry_watcher_t(HKEY rootKey, _In_ PCWSTR subKey, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
{
|
||||
static_assert(wistd::is_same<void, result>::value, "this constructor requires exceptions; use the create method");
|
||||
create(rootKey, subKey, isRecursive, wistd::move(callback));
|
||||
}
|
||||
|
||||
registry_watcher_t(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
{
|
||||
static_assert(wistd::is_same<void, result>::value, "this constructor requires exceptions; use the create method");
|
||||
create(wistd::move(keyToWatch), isRecursive, wistd::move(callback));
|
||||
}
|
||||
|
||||
// Pass a root key, sub key pair or use an empty string to use rootKey as the key to watch.
|
||||
result create(HKEY rootKey, _In_ PCWSTR subKey, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
{
|
||||
// Most use will want to create the key, consider adding an option for open as a future design change.
|
||||
unique_hkey keyToWatch;
|
||||
HRESULT hr = HRESULT_FROM_WIN32(RegCreateKeyExW(rootKey, subKey, 0, nullptr, 0, KEY_NOTIFY, nullptr, &keyToWatch, nullptr));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return err_policy::HResult(hr);
|
||||
}
|
||||
return err_policy::HResult(create_common(wistd::move(keyToWatch), isRecursive, wistd::move(callback)));
|
||||
}
|
||||
|
||||
result create(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
{
|
||||
return err_policy::HResult(create_common(wistd::move(keyToWatch), isRecursive, wistd::move(callback)));
|
||||
}
|
||||
|
||||
private:
|
||||
// Factored into a standalone function to support Clang which does not support conversion of stateless lambdas
|
||||
// to __stdcall
|
||||
static void __stdcall callback(PTP_CALLBACK_INSTANCE, void *context, TP_WAIT *, TP_WAIT_RESULT)
|
||||
{
|
||||
#ifndef __WIL_REGISTRY_CHANGE_CALLBACK_TEST
|
||||
#define __WIL_REGISTRY_CHANGE_CALLBACK_TEST
|
||||
#endif
|
||||
__WIL_REGISTRY_CHANGE_CALLBACK_TEST
|
||||
auto watcherState = static_cast<details::registry_watcher_state *>(context);
|
||||
if (watcherState->TryAddRef())
|
||||
{
|
||||
// using auto reset event so don't need to manually reset.
|
||||
|
||||
// failure here is a programming error.
|
||||
const LSTATUS error = RegNotifyChangeKeyValue(watcherState->m_keyToWatch.get(), watcherState->m_isRecursive,
|
||||
REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_THREAD_AGNOSTIC,
|
||||
watcherState->m_eventHandle.get(), TRUE);
|
||||
|
||||
// Call the client before re-arming to ensure that multiple callbacks don't
|
||||
// run concurrently.
|
||||
switch (error)
|
||||
{
|
||||
case ERROR_SUCCESS:
|
||||
case ERROR_ACCESS_DENIED:
|
||||
// Normal modification: send RegistryChangeKind::Modify and re-arm.
|
||||
watcherState->m_callback(RegistryChangeKind::Modify);
|
||||
watcherState->ReleaseFromCallback(true);
|
||||
break;
|
||||
|
||||
case ERROR_KEY_DELETED:
|
||||
// Key deleted, send RegistryChangeKind::Delete, do not re-arm.
|
||||
watcherState->m_callback(RegistryChangeKind::Delete);
|
||||
watcherState->ReleaseFromCallback(false);
|
||||
break;
|
||||
|
||||
case ERROR_HANDLE_REVOKED:
|
||||
// Handle revoked. This can occur if the user session ends before
|
||||
// the watcher shuts-down. Disarm silently since there is generally no way to respond.
|
||||
watcherState->ReleaseFromCallback(false);
|
||||
break;
|
||||
|
||||
default:
|
||||
FAIL_FAST_HR(HRESULT_FROM_WIN32(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This function exists to avoid template expansion of this code based on err_policy.
|
||||
HRESULT create_common(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
{
|
||||
wistd::unique_ptr<details::registry_watcher_state> watcherState(new(std::nothrow) details::registry_watcher_state(
|
||||
wistd::move(keyToWatch), isRecursive, wistd::move(callback)));
|
||||
RETURN_IF_NULL_ALLOC(watcherState);
|
||||
RETURN_IF_FAILED(watcherState->m_eventHandle.create());
|
||||
RETURN_IF_WIN32_ERROR(RegNotifyChangeKeyValue(watcherState->m_keyToWatch.get(),
|
||||
watcherState->m_isRecursive, REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_THREAD_AGNOSTIC,
|
||||
watcherState->m_eventHandle.get(), TRUE));
|
||||
|
||||
watcherState->m_threadPoolWait.reset(CreateThreadpoolWait(®istry_watcher_t::callback, watcherState.get(), nullptr));
|
||||
RETURN_LAST_ERROR_IF(!watcherState->m_threadPoolWait);
|
||||
storage_t::reset(watcherState.release()); // no more failures after this, pass ownership
|
||||
SetThreadpoolWait(storage_t::get()->m_threadPoolWait.get(), storage_t::get()->m_eventHandle.get(), nullptr);
|
||||
return S_OK;
|
||||
}
|
||||
};
|
||||
|
||||
typedef unique_any_t<registry_watcher_t<details::unique_storage<details::registry_watcher_state_resource_policy>, err_returncode_policy>> unique_registry_watcher_nothrow;
|
||||
typedef unique_any_t<registry_watcher_t<details::unique_storage<details::registry_watcher_state_resource_policy>, err_failfast_policy>> unique_registry_watcher_failfast;
|
||||
|
||||
inline unique_registry_watcher_nothrow make_registry_watcher_nothrow(HKEY rootKey, _In_ PCWSTR subKey, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback) WI_NOEXCEPT
|
||||
{
|
||||
unique_registry_watcher_nothrow watcher;
|
||||
watcher.create(rootKey, subKey, isRecursive, wistd::move(callback));
|
||||
return watcher; // caller must test for success using if (watcher)
|
||||
}
|
||||
|
||||
inline unique_registry_watcher_nothrow make_registry_watcher_nothrow(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback) WI_NOEXCEPT
|
||||
{
|
||||
unique_registry_watcher_nothrow watcher;
|
||||
watcher.create(wistd::move(keyToWatch), isRecursive, wistd::move(callback));
|
||||
return watcher; // caller must test for success using if (watcher)
|
||||
}
|
||||
|
||||
inline unique_registry_watcher_failfast make_registry_watcher_failfast(HKEY rootKey, _In_ PCWSTR subKey, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
{
|
||||
return unique_registry_watcher_failfast(rootKey, subKey, isRecursive, wistd::move(callback));
|
||||
}
|
||||
|
||||
inline unique_registry_watcher_failfast make_registry_watcher_failfast(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
{
|
||||
return unique_registry_watcher_failfast(wistd::move(keyToWatch), isRecursive, wistd::move(callback));
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
typedef unique_any_t<registry_watcher_t<details::unique_storage<details::registry_watcher_state_resource_policy>, err_exception_policy >> unique_registry_watcher;
|
||||
|
||||
inline unique_registry_watcher make_registry_watcher(HKEY rootKey, _In_ PCWSTR subKey, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
{
|
||||
return unique_registry_watcher(rootKey, subKey, isRecursive, wistd::move(callback));
|
||||
}
|
||||
|
||||
inline unique_registry_watcher make_registry_watcher(unique_hkey &&keyToWatch, bool isRecursive, wistd::function<void(RegistryChangeKind)> &&callback)
|
||||
{
|
||||
return unique_registry_watcher(wistd::move(keyToWatch), isRecursive, wistd::move(callback));
|
||||
}
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
} // namespace wil
|
||||
|
||||
#endif
|
||||
6014
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/resource.h
vendored
Normal file
1275
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/result.h
vendored
Normal file
5940
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/result_macros.h
vendored
Normal file
127
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/result_originate.h
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
|
||||
// Note: When origination is enabled by including this file, origination is done as part of the RETURN_* and THROW_* macros. Before originating
|
||||
// a new error we will observe whether there is already an error payload associated with the current thread. If there is, and the HRESULTs match,
|
||||
// then a new error will not be originated. Otherwise we will overwrite it with a new origination. The ABI boundary for WinRT APIs will check the
|
||||
// per-thread error information. The act of checking the error clears it, so there should be minimal risk of failing to originate distinct errors
|
||||
// simply because the HRESULTs match.
|
||||
//
|
||||
// For THROW_ macros we will examine the thread-local error storage once per throw. So typically once, with additional calls if the exception is
|
||||
// caught and re-thrown.
|
||||
//
|
||||
// For RETURN_ macros we will have to examine the thread-local error storage once per frame as the call stack unwinds. Because error conditions
|
||||
// -should- be uncommon the performance impact of checking TLS should be minimal. The more expensive part is originating the error because it must
|
||||
// capture the entire stack and some additional data.
|
||||
|
||||
#ifndef __WIL_RESULT_ORIGINATE_INCLUDED
|
||||
#define __WIL_RESULT_ORIGINATE_INCLUDED
|
||||
|
||||
#include "result.h"
|
||||
#include <OleAuto.h> // RestrictedErrorInfo uses BSTRs :(
|
||||
#include "resource.h"
|
||||
#include "com.h"
|
||||
#include <roerrorapi.h>
|
||||
|
||||
#ifndef __cplusplus_winrt // The CX runtime likes to originate errors already so we would conflict with them.
|
||||
namespace wil
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
// Note: The name must begin with "Raise" so that the !analyze auto-bucketing will ignore this stack frame. Otherwise this line of code gets all the blame.
|
||||
inline void __stdcall RaiseRoOriginateOnWilExceptions(wil::FailureInfo const& failure) WI_NOEXCEPT
|
||||
{
|
||||
if ((failure.type == FailureType::Return) || (failure.type == FailureType::Exception))
|
||||
{
|
||||
bool shouldOriginate = true;
|
||||
|
||||
wil::com_ptr_nothrow<IRestrictedErrorInfo> restrictedErrorInformation;
|
||||
if (GetRestrictedErrorInfo(&restrictedErrorInformation) == S_OK)
|
||||
{
|
||||
// This thread already has an error origination payload. Don't originate again if it has the same HRESULT that we are
|
||||
// observing right now.
|
||||
wil::unique_bstr descriptionUnused;
|
||||
HRESULT existingHr = failure.hr;
|
||||
wil::unique_bstr restrictedDescriptionUnused;
|
||||
wil::unique_bstr capabilitySidUnused;
|
||||
if (SUCCEEDED(restrictedErrorInformation->GetErrorDetails(&descriptionUnused, &existingHr, &restrictedDescriptionUnused, &capabilitySidUnused)))
|
||||
{
|
||||
shouldOriginate = (failure.hr != existingHr);
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldOriginate)
|
||||
{
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
|
||||
wil::unique_hmodule errorModule;
|
||||
if (GetModuleHandleExW(0, L"api-ms-win-core-winrt-error-l1-1-1.dll", &errorModule))
|
||||
{
|
||||
auto pfn = reinterpret_cast<decltype(&::RoOriginateError)>(GetProcAddress(errorModule.get(), "RoOriginateError"));
|
||||
if (pfn != nullptr)
|
||||
{
|
||||
pfn(failure.hr, nullptr);
|
||||
}
|
||||
}
|
||||
#else // DESKTOP | SYSTEM
|
||||
::RoOriginateError(failure.hr, nullptr);
|
||||
#endif // DESKTOP | SYSTEM
|
||||
}
|
||||
else if (restrictedErrorInformation)
|
||||
{
|
||||
// GetRestrictedErrorInfo returns ownership of the error information. If we aren't originating, and an error was already present,
|
||||
// then we need to restore the error information for later observation.
|
||||
SetRestrictedErrorInfo(restrictedErrorInformation.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This method will check for the presence of stowed exception data on the current thread. If such data exists, and the HRESULT
|
||||
// matches the current failure, then we will call RoFailFastWithErrorContext. RoFailFastWithErrorContext in this situation will
|
||||
// result in -VASTLY- improved crash bucketing. It is hard to express just how much better. In other cases we just return and
|
||||
// the calling method fails fast the same way it always has.
|
||||
inline void __stdcall FailfastWithContextCallback(wil::FailureInfo const& failure) WI_NOEXCEPT
|
||||
{
|
||||
wil::com_ptr_nothrow<IRestrictedErrorInfo> restrictedErrorInformation;
|
||||
if (GetRestrictedErrorInfo(&restrictedErrorInformation) == S_OK)
|
||||
{
|
||||
wil::unique_bstr descriptionUnused;
|
||||
HRESULT existingHr = failure.hr;
|
||||
wil::unique_bstr restrictedDescriptionUnused;
|
||||
wil::unique_bstr capabilitySidUnused;
|
||||
if (SUCCEEDED(restrictedErrorInformation->GetErrorDetails(&descriptionUnused, &existingHr, &restrictedDescriptionUnused, &capabilitySidUnused)) &&
|
||||
(existingHr == failure.hr))
|
||||
{
|
||||
// GetRestrictedErrorInfo returns ownership of the error information. We want it to be available for RoFailFastWithErrorContext
|
||||
// so we must restore it via SetRestrictedErrorInfo first.
|
||||
SetRestrictedErrorInfo(restrictedErrorInformation.get());
|
||||
RoFailFastWithErrorContext(existingHr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The error didn't match the current failure. Put it back in thread-local storage even though we aren't failing fast
|
||||
// in this method, so it is available in the debugger just-in-case.
|
||||
SetRestrictedErrorInfo(restrictedErrorInformation.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace details
|
||||
} // namespace wil
|
||||
|
||||
// Automatically call RoOriginateError upon error origination by including this file
|
||||
WI_HEADER_INITITALIZATION_FUNCTION(ResultStowedExceptionInitialize, []
|
||||
{
|
||||
::wil::SetOriginateErrorCallback(::wil::details::RaiseRoOriginateOnWilExceptions);
|
||||
::wil::SetFailfastWithContextCallback(::wil::details::FailfastWithContextCallback);
|
||||
return 1;
|
||||
});
|
||||
#endif // __cplusplus_winrt
|
||||
|
||||
#endif // __WIL_RESULT_ORIGINATE_INCLUDED
|
||||
206
packages/Microsoft.Windows.ImplementationLibrary.1.0.191107.2/include/wil/rpc_helpers.h
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
#ifndef __WIL_RPC_HELPERS_INCLUDED
|
||||
#define __WIL_RPC_HELPERS_INCLUDED
|
||||
|
||||
#include "result.h"
|
||||
#include "resource.h"
|
||||
#include "wistd_functional.h"
|
||||
#include "wistd_type_traits.h"
|
||||
|
||||
namespace wil
|
||||
{
|
||||
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
// This call-adapter template converts a void-returning 'wistd::invoke' into
|
||||
// an HRESULT-returning 'wistd::invoke' that emits S_OK. It can be eliminated
|
||||
// with 'if constexpr' when C++17 is in wide use.
|
||||
template<typename TReturnType> struct call_adapter
|
||||
{
|
||||
template<typename... TArgs> static HRESULT call(TArgs&& ... args)
|
||||
{
|
||||
return wistd::invoke(wistd::forward<TArgs>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct call_adapter<void>
|
||||
{
|
||||
template<typename... TArgs> static HRESULT call(TArgs&& ... args)
|
||||
{
|
||||
wistd::invoke(wistd::forward<TArgs>(args)...);
|
||||
return S_OK;
|
||||
}
|
||||
};
|
||||
|
||||
// Some RPC exceptions are already HRESULTs. Others are in the regular Win32
|
||||
// error space. If the incoming exception code isn't an HRESULT, wrap it.
|
||||
constexpr HRESULT map_rpc_exception(DWORD code)
|
||||
{
|
||||
return IS_ERROR(code) ? code : __HRESULT_FROM_WIN32(code);
|
||||
}
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
/** Invokes an RPC method, mapping structured exceptions to HRESULTs
|
||||
Failures encountered by the RPC infrastructure (such as server crashes, authentication
|
||||
errors, client parameter issues, etc.) are emitted by raising a structured exception from
|
||||
within the RPC machinery. This method wraps the requested call in the usual RpcTryExcept,
|
||||
RpcTryCatch, and RpcEndExcept sequence then maps the exceptions to HRESULTs for the usual
|
||||
flow control machinery to use.
|
||||
|
||||
Many RPC methods are defined as returning HRESULT themselves, where the HRESULT indicates
|
||||
the result of the _work_. HRESULTs returned by a successful completion of the _call_ are
|
||||
returned as-is.
|
||||
|
||||
RPC methods that have a return type of 'void' are mapped to returning S_OK when the _call_
|
||||
completes successfully.
|
||||
|
||||
For example, consider an RPC interface method defined in idl as:
|
||||
~~~
|
||||
HRESULT GetKittenState([in, ref, string] const wchar_t* name, [out, retval] KittenState** state);
|
||||
~~~
|
||||
To call this method, use:
|
||||
~~~
|
||||
wil::unique_rpc_binding binding = // typically gotten elsewhere;
|
||||
wil::unique_midl_ptr<KittenState> state;
|
||||
HRESULT hr = wil::invoke_rpc_nothrow(GetKittenState, binding.get(), L"fluffy", state.put());
|
||||
RETURN_IF_FAILED(hr);
|
||||
~~~
|
||||
*/
|
||||
template<typename... TCall> HRESULT invoke_rpc_nothrow(TCall&&... args) WI_NOEXCEPT
|
||||
{
|
||||
RpcTryExcept
|
||||
{
|
||||
// Note: this helper type can be removed with C++17 enabled via
|
||||
// 'if constexpr(wistd::is_same_v<void, result_t>)'
|
||||
using result_t = typename wistd::__invoke_of<TCall...>::type;
|
||||
RETURN_IF_FAILED(details::call_adapter<result_t>::call(wistd::forward<TCall>(args)...));
|
||||
return S_OK;
|
||||
}
|
||||
RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
|
||||
{
|
||||
RETURN_HR(details::map_rpc_exception(RpcExceptionCode()));
|
||||
}
|
||||
RpcEndExcept
|
||||
}
|
||||
|
||||
/** Invokes an RPC method, mapping structured exceptions to HRESULTs
|
||||
Failures encountered by the RPC infrastructure (such as server crashes, authentication
|
||||
errors, client parameter issues, etc.) are emitted by raising a structured exception from
|
||||
within the RPC machinery. This method wraps the requested call in the usual RpcTryExcept,
|
||||
RpcTryCatch, and RpcEndExcept sequence then maps the exceptions to HRESULTs for the usual
|
||||
flow control machinery to use.
|
||||
|
||||
Some RPC methods return results (such as a state enumeration or other value) directly in
|
||||
their signature. This adapter writes that result into a caller-provided object then
|
||||
returns S_OK.
|
||||
|
||||
For example, consider an RPC interface method defined in idl as:
|
||||
~~~
|
||||
GUID GetKittenId([in, ref, string] const wchar_t* name);
|
||||
~~~
|
||||
To call this method, use:
|
||||
~~~
|
||||
wil::unique_rpc_binding binding = // typically gotten elsewhere;
|
||||
GUID id;
|
||||
HRESULT hr = wil::invoke_rpc_result_nothrow(id, GetKittenId, binding.get(), L"fluffy");
|
||||
RETURN_IF_FAILED(hr);
|
||||
~~~
|
||||
*/
|
||||
template<typename TResult, typename... TCall> HRESULT invoke_rpc_result_nothrow(TResult& result, TCall&&... args) WI_NOEXCEPT
|
||||
{
|
||||
RpcTryExcept
|
||||
{
|
||||
result = wistd::invoke(wistd::forward<TCall>(args)...);
|
||||
return S_OK;
|
||||
}
|
||||
RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
|
||||
{
|
||||
RETURN_HR(details::map_rpc_exception(RpcExceptionCode()));
|
||||
}
|
||||
RpcEndExcept
|
||||
}
|
||||
|
||||
namespace details
|
||||
{
|
||||
// Provides an adapter around calling the context-handle-close method on an
|
||||
// RPC interface, which itself is an RPC call.
|
||||
template<typename TStorage, typename close_fn_t, close_fn_t close_fn>
|
||||
struct rpc_closer_t
|
||||
{
|
||||
static void Close(TStorage arg) WI_NOEXCEPT
|
||||
{
|
||||
LOG_IF_FAILED(invoke_rpc_nothrow(close_fn, &arg));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** Manages explicit RPC context handles
|
||||
Explicit RPC context handles are used in many RPC interfaces. Most interfaces with
|
||||
context handles have an explicit `FooClose([in, out] CONTEXT*)` method that lets
|
||||
the server close out the context handle. As the close method itself is an RPC call,
|
||||
it can fail and raise a structured exception.
|
||||
|
||||
This type routes the context-handle-specific `Close` call through the `invoke_rpc_nothrow`
|
||||
helper, ensuring correct cleanup and lifecycle management.
|
||||
~~~
|
||||
// Assume the interface has two methods:
|
||||
// HRESULT OpenFoo([in] handle_t binding, [out] FOO_CONTEXT*);
|
||||
// HRESULT UseFoo([in] FOO_CONTEXT context;
|
||||
// void CloseFoo([in, out] PFOO_CONTEXT);
|
||||
using unique_foo_context = wil::unique_rpc_context_handle<FOO_CONTEXT, decltype(&CloseFoo), CloseFoo>;
|
||||
unique_foo_context context;
|
||||
RETURN_IF_FAILED(wil::invoke_rpc_nothrow(OpenFoo, m_binding.get(), context.put()));
|
||||
RETURN_IF_FAILED(wil::invoke_rpc_nothrow(UseFoo, context.get()));
|
||||
context.reset();
|
||||
~~~
|
||||
*/
|
||||
template<typename TContext, typename close_fn_t, close_fn_t close_fn>
|
||||
using unique_rpc_context_handle = unique_any<TContext, decltype(&details::rpc_closer_t<TContext, close_fn_t, close_fn>::Close), details::rpc_closer_t<TContext, close_fn_t, close_fn>::Close>;
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
/** Invokes an RPC method, mapping structured exceptions to C++ exceptions
|
||||
See `wil::invoke_rpc_nothrow` for additional information. Failures during the _call_
|
||||
and those returned by the _method_ are mapped to HRESULTs and thrown inside a
|
||||
wil::ResultException. Using the example RPC method provided above:
|
||||
~~~
|
||||
wil::unique_midl_ptr<KittenState> state;
|
||||
wil::invoke_rpc(GetKittenState, binding.get(), L"fluffy", state.put());
|
||||
// use 'state'
|
||||
~~~
|
||||
*/
|
||||
template<typename... TCall> void invoke_rpc(TCall&& ... args)
|
||||
{
|
||||
THROW_IF_FAILED(invoke_rpc_nothrow(wistd::forward<TCall>(args)...));
|
||||
}
|
||||
|
||||
/** Invokes an RPC method, mapping structured exceptions to C++ exceptions
|
||||
See `wil::invoke_rpc_result_nothrow` for additional information. Failures during the
|
||||
_call_ are mapped to HRESULTs and thrown inside a `wil::ResultException`. Using the
|
||||
example RPC method provided above:
|
||||
~~~
|
||||
GUID id = wil::invoke_rpc_result(GetKittenId, binding.get());
|
||||
// use 'id'
|
||||
~~~
|
||||
*/
|
||||
template<typename... TCall> auto invoke_rpc_result(TCall&& ... args)
|
||||
{
|
||||
using result_t = typename wistd::__invoke_of<TCall...>::type;
|
||||
result_t result{};
|
||||
THROW_IF_FAILED(invoke_rpc_result_nothrow(result, wistd::forward<TCall>(args)...));
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||