-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multiprofile's Delete API modify #3069
base: MultipleFile_Delete
Are you sure you want to change the base?
Changes from 7 commits
3b46d95
710afd2
3a0c4aa
e834d1e
70e7a7f
4e428e2
33cda74
767d420
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -169,20 +169,71 @@ void ScenarioCookieManagement::DeleteAllCookies() | |
### Delete profile | ||
|
||
```cpp | ||
HRESULT AppWindow::DeleteProfile(ICoreWebView2Controller* controller) | ||
HRESULT AppWindow::DeleteProfile(ICoreWebView2* webView2) | ||
{ | ||
wil::com_ptr<ICoreWebView2> coreWebView2; | ||
CHECK_FAILURE(controller->get_CoreWebView2(&coreWebView2)); | ||
auto webview7 = coreWebView2.try_query<ICoreWebView2_7>(); | ||
if (webview7) | ||
{ | ||
wil::com_ptr<ICoreWebView2Profile> profile; | ||
CHECK_FAILURE(webview7->get_Profile(&profile)); | ||
auto profile2 = profile.try_query<ICoreWebView2StagingProfile4>(); | ||
if (profile2) | ||
{ | ||
CHECK_FAILURE(profile2->Delete()); | ||
} | ||
wil::com_ptr<ICoreWebView2Profile> profile; | ||
CHECK_FAILURE(webView2->get_Profile(&profile)); | ||
CHECK_FAILURE(profile2->Delete()); | ||
} | ||
|
||
void AppWindow::RegisterEventHandlers() | ||
{ | ||
BOOL isWebview2Closed = FALSE; | ||
CHECK_FAILURE(webView2->get_IsClosed(&isWebview2Closed)); | ||
if (!isWebview2Closed) { | ||
CHECK_FAILURE(m_webView->add_Closed( | ||
Microsoft::WRL::Callback<ICoreWebView2ClosedEventHandler>( | ||
[this](ICoreWebView2_20* sender, ICoreWebView2EventArgs* args) | ||
{ | ||
COREWEBVIEW2_CLOSED_REASON reason; | ||
CHECK_FAILURE(args->get_Reason(&reason)); | ||
std::wstring message; | ||
switch (reason) | ||
{ | ||
case COREWEBVIEW2_CLOSED_REASON::COREWEBVIEW2_CLOSED_REASON_SHUTDOWN: | ||
{ | ||
message = L"The CoreWebView2 has closed because the corresponding " | ||
L"CoreWebView2Controller had its Close method called either " | ||
L"explicitly or implicitly."; | ||
break; | ||
} | ||
case COREWEBVIEW2_CLOSED_REASON:: | ||
COREWEBVIEW2_CLOSED_REASON_BROWSER_PROCESS_FAILURE: | ||
{ | ||
message = L"The CoreWebView2 has closed because its browser process " | ||
L"crashed. The Closed event will be raised after the " | ||
L"ProcessFailed event is raised."; | ||
break; | ||
} | ||
case COREWEBVIEW2_CLOSED_REASON:: | ||
COREWEBVIEW2_CLOSED_REASON_BROWSER_PROCESS_EXITED: | ||
{ | ||
message = L"The CoreWebView2 has closed because its browser process has " | ||
L"exited."; | ||
break; | ||
} | ||
case COREWEBVIEW2_CLOSED_REASON:: | ||
COREWEBVIEW2_CLOSED_REASON_PARENT_WINDOW_CLOSED: | ||
{ | ||
message = L"The CoreWebView2 has closed because its parent window was " | ||
L"closed."; | ||
break; | ||
} | ||
case COREWEBVIEW2_CLOSED_REASON::COREWEBVIEW2_CLOSED_REASON_PROFILE_DELETED: | ||
{ | ||
message = L"The CoreWebView2 has closed because its corresponding " | ||
L"Profile has been or marked as deleted."; | ||
break; | ||
} | ||
} | ||
RunAsync([this, message]() | ||
{ | ||
MessageBox( | ||
m_mainWindow, message.c_str(), L"webview2 closed", MB_OK); | ||
CloseAppWindow(); | ||
}); | ||
return S_OK; | ||
}).Get(), nullptr)); | ||
} | ||
} | ||
``` | ||
|
@@ -253,10 +304,56 @@ public DeleteProfile(CoreWebView2Controller controller) | |
{ | ||
// Get the profile object. | ||
CoreWebView2Profile profile = controller.CoreWebView2.Profile; | ||
|
||
// Delete current profile. | ||
profile.Delete(); | ||
} | ||
|
||
void WebView_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e) | ||
{ | ||
if (!webView.IsClosed) { | ||
webView.CoreWebView2.Closed += CoreWebView2_Closed; | ||
} | ||
} | ||
|
||
private void CoreWebView2_Closed(object sender, CoreWebView2ClosedEventArgs e) | ||
{ | ||
String message; | ||
switch (e.Reason) | ||
{ | ||
case CoreWebView2ClosedReason.ShutDown: | ||
{ | ||
message = "The CoreWebView2 has closed because the corresponding CoreWebView2Controller had its Close method called either explicitly or implicitly." | ||
break; | ||
} | ||
case CoreWebView2ClosedReason.BrowserProcessFailure: | ||
{ | ||
message = "The CoreWebView2 has closed because its browser process crashed. The Closed event will be raised after the ProcessFailed event is raised." | ||
break; | ||
} | ||
case CoreWebView2ClosedReason.BrowserProcessExited: | ||
{ | ||
message = "The CoreWebView2 has closed because its browser process has exited." | ||
break; | ||
} | ||
case CoreWebView2ClosedReason.ParentWindowClosed: | ||
{ | ||
message = "The CoreWebView2 has closed because its parent window was closed." | ||
break; | ||
} | ||
case CoreWebView2ClosedReason.ProfileDeleted: | ||
{ | ||
message = "The CoreWebView2 has closed because its corresponding Profile has been or marked as deleted." | ||
break; | ||
} | ||
} | ||
|
||
this.Dispatcher.InvokeAsync(() => | ||
{ | ||
MessageBox.Show(message); | ||
Close(); | ||
}); | ||
} | ||
``` | ||
|
||
# API Details | ||
|
@@ -267,9 +364,13 @@ public DeleteProfile(CoreWebView2Controller controller) | |
interface ICoreWebView2ControllerOptions; | ||
interface ICoreWebView2Environment5; | ||
interface ICoreWebView2_7; | ||
interface ICoreWebView2_9; | ||
interface ICoreWebView2Profile; | ||
interface ICoreWebView2Profile2; | ||
interface ICoreWebView2Profile3; | ||
interface ICoreWebView2Profile4; | ||
interface ICoreWebView2ClosedEventHandler; | ||
interface ICoreWebView2ClosedEventArgs; | ||
|
||
/// This interface is used to manage profile options that created by 'CreateCoreWebView2ControllerOptions'. | ||
[uuid(C2669A3A-03A9-45E9-97EA-03CD55E5DC03), object, pointer_default(unique)] | ||
|
@@ -363,17 +464,80 @@ interface ICoreWebView2Profile2 : ICoreWebView2Profile { | |
[propget] HRESULT CookieManager([out, retval] ICoreWebView2CookieManager** cookieManager); | ||
} | ||
|
||
[uuid(1c1ae2cc-d5c2-ffe3-d3e7-7857035d23b7), object, pointer_default(unique)] | ||
interface ICoreWebView2Profile3 : ICoreWebView2Profile2 { | ||
/// All webviews on this profile will be closed, and the profile will be marked for deletion. | ||
/// After the Delete() call completes, The render process of webviews on this profile will | ||
/// asynchronously exit with the reason:`COREWEBVIEW2_PROCESS_FAILED_REASON_PROFILE_DELETED`. | ||
/// See 'COREWEBVIEW2_PROCESS_FAILED_REASON::COREWEBVIEW2_PROCESS_FAILED_REASON_PROFILE_DELETED' | ||
/// for more details. The profile directory on disk will be actually deleted when the browser | ||
/// process exits. Webview2 creation will fail with the HRESULT is ERROR_INVALID_STATE(0x8007139FL) | ||
/// if you create it with the same name as a profile that is being deleted. | ||
HRESULT Delete(); | ||
[uuid(2765B8BD-7C57-4B76-B8AA-1EC940FE92CC), object, pointer_default(unique)] | ||
interface ICoreWebView2Profile4 : IUnknown { | ||
/// After the API is called, the profile will be marked for deletion. The | ||
/// local profile's directory will be tried to delete at browser process | ||
/// exit, if fail to delete, it will recursively try to delete at next | ||
/// browser process start until successful. | ||
/// The corresponding webview2s will be auto closed and its Closed event | ||
/// handle function will be triggered with the reason is | ||
/// COREWEBVIEW2_CLOSED_REASON.COREWEBVIEW2_CLOSED_REASON_PROFILE_DELETED. | ||
/// If create a new profile with the same name as the profile that has been | ||
/// marked as deleted will be failure with the HRESULT:ERROR_INVALID_STATE | ||
/// (0x8007139FL). | ||
HRESULT Delete(); | ||
} | ||
|
||
[uuid(cc39bea3-f6f8-471b-919f-fa253e2fff03), object, pointer_default(unique)] | ||
interface ICoreWebView2_9 : IUnknown { | ||
/// Add an event handler for the `Closed` event. `Closed` enent handle runs | ||
/// when the webview2 is closed due to the reason that described in the | ||
/// COREWEBVIEW2_CLOSED_REASON enumeration. When this event is raised, the | ||
/// webview2 moves to the Closed state, and cannot be used anymore. | ||
HRESULT add_Closed( | ||
[in] ICoreWebView2ClosedEventHandler* eventHandler, | ||
[out] EventRegistrationToken* token); | ||
|
||
/// Remove an event handler previously added with `add_Closed`. | ||
HRESULT remove_Closed( | ||
[in] EventRegistrationToken token); | ||
|
||
/// `TRUE` if WebView2 has moved to the Closed state. Use `add_Closed` API | ||
/// to get the specific closed reason. For more information see `add_Closed`. | ||
[propget] HRESULT IsClosed([out, retval] BOOL* value); | ||
} | ||
|
||
/// The reason of webview2 closed. | ||
[v1_enum] | ||
typedef enum COREWEBVIEW2_CLOSED_REASON { | ||
/// The CoreWebView2 has closed because the corresponding | ||
/// CoreWebView2Controller had its Close method called either explicitly or | ||
/// implicitly. | ||
COREWEBVIEW2_CLOSED_REASON_SHUTDOWN, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If developers explicitly called And, what scenario do you imagine that the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove this Close event's Enum value and add them in latter PR. |
||
|
||
/// The CoreWebView2 has closed because its browser process crashed. | ||
/// The Closed event will be raised after the ProcessFailed event is raised. | ||
COREWEBVIEW2_CLOSED_REASON_BROWSER_PROCESS_FAILURE, | ||
|
||
/// The CoreWebView2 has closed because its browser process has exited. | ||
COREWEBVIEW2_CLOSED_REASON_BROWSER_PROCESS_EXITED, | ||
yunate marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/// The CoreWebView2 has closed because its parent window was closed. | ||
COREWEBVIEW2_CLOSED_REASON_PARENT_WINDOW_CLOSED, | ||
|
||
/// The CoreWebView2 has closed because its corresponding Profile has been or | ||
/// marked as deleted. | ||
COREWEBVIEW2_CLOSED_REASON_PROFILE_DELETED | ||
} COREWEBVIEW2_CLOSED_REASON; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The two other cases we should add here (we can get the urgent work's implementation in first, and the less urgent parts implementation in a later PR) are for normal webview2 shutdown, and for browser process crash. Maybe this:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I will create a work item to trace this things. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Additional entries for this:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do I need to add those to the API SPEC, or add them one by one in a later PR? |
||
|
||
/// Receives the webview2 `Closed` event. | ||
[uuid(970BB7E0-A257-4A76-BE15-5BDEB00B5673), object, pointer_default(unique)] | ||
interface ICoreWebView2ClosedEventHandler : IUnknown { | ||
/// Called to provide the implementer with the event args for the | ||
/// corresponding event. | ||
HRESULT Invoke([in] ICoreWebView2_20* sender, | ||
[in] ICoreWebView2ClosedEventArgs* args); | ||
} | ||
|
||
/// This is the event args interface for webview2 `Closed` event handle. | ||
[uuid(0e1730c1-03df-4ad2-b847-be4d63adf777), object, pointer_default(unique)] | ||
interface ICoreWebView2ClosedEventArgs : IUnknown { | ||
/// webview2 closed reason. | ||
[propget] HRESULT Reason([out, retval] | ||
COREWEBVIEW2_CLOSED_REASON* value); | ||
} | ||
|
||
``` | ||
|
||
## .NET and WinRT | ||
|
@@ -409,11 +573,35 @@ namespace Microsoft.Web.WebView2.Core | |
CoreWebView2ControllerWindowReference ParentWindow, | ||
CoreWebView2ControllerOptions options); | ||
} | ||
|
||
|
||
runtimeclass WebView2 | ||
{ | ||
bool IsClosed { get; }; | ||
} | ||
|
||
runtimeclass CoreWebView2 | ||
{ | ||
// ... | ||
CoreWebView2Profile Profile { get; }; | ||
|
||
[interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2_9")] | ||
{ | ||
event Windows.Foundation.TypedEventHandler<CoreWebView2, CoreWebView2ClosedEventArgs> Closed; | ||
} | ||
} | ||
|
||
enum CoreWebView2ClosedReason | ||
{ | ||
ShutDown, | ||
BrowserProcessFailure, | ||
BrowserProcessExited, | ||
ParentWindowClosed, | ||
ProfileDeleted, | ||
}; | ||
|
||
runtimeclass CoreWebView2ClosedEventArgs | ||
{ | ||
CoreWebView2ClosedReason Reason { get; }; | ||
} | ||
|
||
runtimeclass CoreWebView2Profile | ||
|
@@ -426,9 +614,9 @@ namespace Microsoft.Web.WebView2.Core | |
|
||
CoreWebView2CookieManager CookieManager { get; }; | ||
|
||
[interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2Profile3")] | ||
[interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2Profile4")] | ||
{ | ||
// ICoreWebView2Profile3 members | ||
// ICoreWebView2Profile4 members | ||
void Delete(); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In addition we should add a property where you can check if the CoreWebView2 is closed or not. This way end dev's asynchronous code that may be in progress when the profile is deleted can check if the CoreWebView2 has closed and take appropriate action.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think do not need this function. Because, close webview and Closed event handle function called are in a same therad and a same loop. So, if the Closed event handle function called, the user has known the webview has been closed, they can record a flag in this function; if before Closed event handle function called, the webview is always still alive.