20
20
21
21
#include " App.h"
22
22
#include " AppStartPage.h"
23
+ #include " AudioComponent.h"
23
24
#include " CheckFailure.h"
24
25
#include " ControlComponent.h"
25
26
#include " DpiUtil.h"
33
34
#include " ScenarioCustomDownloadExperience.h"
34
35
#include " ScenarioDOMContentLoaded.h"
35
36
#include " ScenarioNavigateWithWebResourceRequest.h"
36
- #include " ScenarioVirtualHostMappingForSW.h"
37
37
#include " ScenarioVirtualHostMappingForPopUpWindow.h"
38
+ #include " ScenarioVirtualHostMappingForSW.h"
38
39
#include " ScenarioWebMessage.h"
39
40
#include " ScenarioWebViewEventMonitor.h"
40
41
#include " ScriptComponent.h"
41
42
#include " SettingsComponent.h"
42
43
#include " TextInputDialog.h"
43
44
#include " ViewComponent.h"
45
+
44
46
using namespace Microsoft ::WRL;
45
47
static constexpr size_t s_maxLoadString = 100 ;
46
48
static constexpr UINT s_runAsyncWindowMessage = WM_APP;
@@ -96,9 +98,62 @@ DWORD WINAPI DownloadAndInstallWV2RT(_In_ LPVOID lpParameter)
96
98
return returnCode;
97
99
}
98
100
101
+ static INT_PTR CALLBACK DlgProcStatic (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
102
+ {
103
+ auto app = (AppWindow*)GetWindowLongPtr (hDlg, GWLP_USERDATA);
104
+
105
+ switch (message)
106
+ {
107
+ case WM_INITDIALOG:
108
+ {
109
+ app = (AppWindow*)lParam;
110
+ SetWindowLongPtr (hDlg, GWLP_USERDATA, (LONG_PTR)app);
111
+
112
+ SetDlgItemText (hDlg, IDC_EDIT_PROFILE, app->GetWebViewOption ().profile .c_str ());
113
+ CheckDlgButton (hDlg, IDC_CHECK_INPRIVATE, app->GetWebViewOption ().isInPrivate );
114
+ return (INT_PTR)TRUE ;
115
+ }
116
+ case WM_COMMAND:
117
+ {
118
+ if (LOWORD (wParam) == IDOK)
119
+ {
120
+ int length = GetWindowTextLength (GetDlgItem (hDlg, IDC_EDIT_PROFILE));
121
+ wchar_t text[MAX_PATH] = {};
122
+ GetDlgItemText (hDlg, IDC_EDIT_PROFILE, text, length + 1 );
123
+ bool inPrivate = IsDlgButtonChecked (hDlg, IDC_CHECK_INPRIVATE);
124
+
125
+ WebViewCreateOption opt (std::wstring (std::move (text)), inPrivate, WebViewCreateEntry::EVER_FROM_CREATE_WITH_OPTION_MENU);
126
+
127
+ // create app window
128
+ new AppWindow (app->GetCreationModeId (), opt);
129
+ }
130
+
131
+ if (LOWORD (wParam) == IDOK || LOWORD (wParam) == IDCANCEL)
132
+ {
133
+ EndDialog (hDlg, LOWORD (wParam));
134
+ return (INT_PTR)TRUE ;
135
+ }
136
+ break ;
137
+ }
138
+ case WM_NCDESTROY:
139
+ SetWindowLongPtr (hDlg, GWLP_USERDATA, NULL );
140
+ return (INT_PTR)TRUE ;
141
+ }
142
+ return (INT_PTR)FALSE ;
143
+ }
144
+
145
+ void WebViewCreateOption::PopupDialog (AppWindow* app)
146
+ {
147
+ DialogBoxParam (
148
+ g_hInstance, MAKEINTRESOURCE (IDD_WEBVIEW2_OPTION), app->GetMainWindow (), DlgProcStatic,
149
+ (LPARAM)app);
150
+ }
151
+
152
+
99
153
// Creates a new window which is a copy of the entire app, but on the same thread.
100
154
AppWindow::AppWindow (
101
155
UINT creationModeId,
156
+ const WebViewCreateOption& opt,
102
157
const std::wstring& initialUri,
103
158
const std::wstring& userDataFolderParam,
104
159
bool isMainWindow,
@@ -108,11 +163,13 @@ AppWindow::AppWindow(
108
163
bool shouldHaveToolbar
109
164
)
110
165
: m_creationModeId(creationModeId),
166
+ m_webviewOption(opt),
111
167
m_initialUri(initialUri),
112
168
m_onWebViewFirstInitialized(webviewCreatedCallback)
113
169
{
114
170
// Initialize COM as STA.
115
171
CHECK_FAILURE (OleInitialize (NULL ));
172
+
116
173
++s_appInstances;
117
174
118
175
WCHAR szTitle[s_maxLoadString]; // The title bar text
@@ -580,7 +637,7 @@ bool AppWindow::ExecuteAppCommands(WPARAM wParam, LPARAM lParam)
580
637
InitializeWebView ();
581
638
return true ;
582
639
case IDM_NEW_WINDOW:
583
- new AppWindow (m_creationModeId);
640
+ new AppWindow (m_creationModeId, GetWebViewOption () );
584
641
return true ;
585
642
case IDM_NEW_THREAD:
586
643
CreateNewThread (this );
@@ -591,6 +648,9 @@ bool AppWindow::ExecuteAppCommands(WPARAM wParam, LPARAM lParam)
591
648
case IDM_TOGGLE_AAD_SSO:
592
649
ToggleAADSSO ();
593
650
return true ;
651
+ case IDM_CREATE_WITH_OPTION:
652
+ m_webviewOption.PopupDialog (this );
653
+ return true ;
594
654
case IDM_TOGGLE_TOPMOST_WINDOW:
595
655
{
596
656
bool isCurrentlyTopMost = (GetWindowLong (m_mainWindow, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0 ;
@@ -674,7 +734,7 @@ std::function<void()> AppWindow::GetAcceleratorKeyFunction(UINT key)
674
734
switch (key)
675
735
{
676
736
case ' N' :
677
- return [this ] { new AppWindow (m_creationModeId); };
737
+ return [this ] { new AppWindow (m_creationModeId, GetWebViewOption () ); };
678
738
case ' Q' :
679
739
return [this ] { CloseAppWindow (); };
680
740
case ' S' :
@@ -802,6 +862,11 @@ HRESULT AppWindow::OnCreateEnvironmentCompleted(
802
862
CHECK_FAILURE (result);
803
863
m_webViewEnvironment = environment;
804
864
865
+ if (m_webviewOption.entry == WebViewCreateEntry::EVER_FROM_CREATE_WITH_OPTION_MENU)
866
+ {
867
+ return CreateControllerWithOptions ();
868
+ }
869
+
805
870
auto webViewEnvironment3 =
806
871
m_webViewEnvironment.try_query <ICoreWebView2Environment3>();
807
872
#ifdef USE_WEBVIEW2_WIN10
@@ -836,6 +901,86 @@ HRESULT AppWindow::OnCreateEnvironmentCompleted(
836
901
}
837
902
// ! [CreateCoreWebView2Controller]
838
903
904
+ HRESULT AppWindow::CreateControllerWithOptions ()
905
+ {
906
+ auto webViewEnvironment8 =
907
+ m_webViewEnvironment.try_query <ICoreWebView2ExperimentalEnvironment8>();
908
+ if (!webViewEnvironment8)
909
+ {
910
+ FeatureNotAvailable ();
911
+ return S_OK;
912
+ }
913
+
914
+ Microsoft::WRL::ComPtr<ICoreWebView2ExperimentalControllerOptions> options;
915
+ HRESULT hr = webViewEnvironment8->CreateCoreWebView2ControllerOptions (
916
+ m_webviewOption.profile .c_str (), m_webviewOption.isInPrivate , options.GetAddressOf ());
917
+ if (hr == E_INVALIDARG)
918
+ {
919
+ ShowFailure (hr, L" Unable to create WebView2 due to an invalid profile name." );
920
+ CloseAppWindow ();
921
+ return S_OK;
922
+ }
923
+ CHECK_FAILURE (hr);
924
+
925
+ #ifdef USE_WEBVIEW2_WIN10
926
+ if (m_dcompDevice || m_wincompCompositor)
927
+ #else
928
+ if (m_dcompDevice)
929
+ #endif
930
+ {
931
+ CHECK_FAILURE (webViewEnvironment8->CreateCoreWebView2CompositionControllerWithOptions (
932
+ m_mainWindow, options.Get (),
933
+ Callback<ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler>(
934
+ [this ](
935
+ HRESULT result,
936
+ ICoreWebView2CompositionController* compositionController) -> HRESULT {
937
+ auto controller =
938
+ wil::com_ptr<ICoreWebView2CompositionController>(compositionController)
939
+ .query <ICoreWebView2Controller>();
940
+ return OnCreateCoreWebView2ControllerCompleted (result, controller.get ());
941
+ })
942
+ .Get ()));
943
+ }
944
+ else
945
+ {
946
+ CHECK_FAILURE (webViewEnvironment8->CreateCoreWebView2ControllerWithOptions (
947
+ m_mainWindow, options.Get (),
948
+ Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(
949
+ this , &AppWindow::OnCreateCoreWebView2ControllerCompleted)
950
+ .Get ()));
951
+ }
952
+
953
+ return S_OK;
954
+ }
955
+
956
+ void AppWindow::SetAppIcon (bool inPrivate)
957
+ {
958
+ HICON newSmallIcon = nullptr ;
959
+ HICON newBigIcon = nullptr ;
960
+ if (inPrivate)
961
+ {
962
+ static HICON smallInPrivateIcon = reinterpret_cast <HICON>(LoadImage (
963
+ g_hInstance, MAKEINTRESOURCEW (IDI_WEBVIEW2APISAMPLE_INPRIVATE), IMAGE_ICON, 16 , 16 ,
964
+ LR_DEFAULTCOLOR));
965
+ static HICON bigInPrivateIcon = reinterpret_cast <HICON>(LoadImage (
966
+ g_hInstance, MAKEINTRESOURCEW (IDI_WEBVIEW2APISAMPLE_INPRIVATE), IMAGE_ICON, 32 , 32 ,
967
+ LR_DEFAULTCOLOR));
968
+ newSmallIcon = smallInPrivateIcon;
969
+ newBigIcon = bigInPrivateIcon;
970
+ }
971
+ else
972
+ {
973
+ static HICON smallIcon = LoadIcon (g_hInstance, MAKEINTRESOURCE (IDI_WEBVIEW2APISAMPLE));
974
+ static HICON bigIcon = LoadIcon (g_hInstance, MAKEINTRESOURCE (IDI_SMALL));
975
+ newSmallIcon = smallIcon;
976
+ newBigIcon = bigIcon;
977
+ }
978
+ reinterpret_cast <HICON>(SendMessage (
979
+ m_mainWindow, WM_SETICON, ICON_SMALL, reinterpret_cast <LPARAM>(newSmallIcon)));
980
+ reinterpret_cast <HICON>(
981
+ SendMessage (m_mainWindow, WM_SETICON, ICON_BIG, reinterpret_cast <LPARAM>(newBigIcon)));
982
+ }
983
+
839
984
// This is the callback passed to CreateCoreWebView2Controller. Here we initialize all WebView-related
840
985
// state and register most of our event handlers with the WebView.
841
986
HRESULT AppWindow::OnCreateCoreWebView2ControllerCompleted (HRESULT result, ICoreWebView2Controller* controller)
@@ -856,6 +1001,23 @@ HRESULT AppWindow::OnCreateCoreWebView2ControllerCompleted(HRESULT result, ICore
856
1001
// ProcessFailed event could have been raised yet) so the PID is
857
1002
// available.
858
1003
CHECK_FAILURE (m_webView->get_BrowserProcessId (&m_newestBrowserPid));
1004
+ auto webview2Experimental8 = coreWebView2.try_query <ICoreWebView2Experimental8>();
1005
+ if (webview2Experimental8)
1006
+ {
1007
+ wil::com_ptr<ICoreWebView2ExperimentalProfile> profile;
1008
+ CHECK_FAILURE (webview2Experimental8->get_Profile (&profile));
1009
+ wil::unique_cotaskmem_string profile_path;
1010
+ CHECK_FAILURE (profile->get_ProfilePath (&profile_path));
1011
+ std::wstring str (profile_path.get ());
1012
+ m_profileDirName = str.substr (str.find_last_of (L' \\ ' ) + 1 );
1013
+ BOOL inPrivate = FALSE ;
1014
+ CHECK_FAILURE (profile->get_IsInPrivateModeEnabled (&inPrivate));
1015
+ // update window title with m_profileDirName
1016
+ UpdateAppTitle ();
1017
+
1018
+ // update window icon
1019
+ SetAppIcon (inPrivate);
1020
+ }
859
1021
// Create components. These will be deleted when the WebView is closed.
860
1022
NewComponent<FileComponent>(this );
861
1023
NewComponent<ProcessComponent>(this );
@@ -1053,12 +1215,12 @@ void AppWindow::RegisterEventHandlers()
1053
1215
if (!useDefaultWindow)
1054
1216
{
1055
1217
newAppWindow = new AppWindow (
1056
- m_creationModeId, L" none" , m_userDataFolder, false , nullptr , true ,
1057
- windowRect, !!shouldHaveToolbar);
1218
+ m_creationModeId, GetWebViewOption (), L" none" , m_userDataFolder, false ,
1219
+ nullptr , true , windowRect, !!shouldHaveToolbar);
1058
1220
}
1059
1221
else
1060
1222
{
1061
- newAppWindow = new AppWindow (m_creationModeId, L" none" );
1223
+ newAppWindow = new AppWindow (m_creationModeId, GetWebViewOption (), L" none" );
1062
1224
}
1063
1225
newAppWindow->m_isPopupWindow = true ;
1064
1226
newAppWindow->m_onWebViewFirstInitialized = [args, deferral, newAppWindow]() {
@@ -1254,6 +1416,9 @@ bool AppWindow::CloseWebView(bool cleanupUserDataFolder)
1254
1416
// BrowserProcessExited event will not be called.
1255
1417
m_webViewEnvironment = nullptr ;
1256
1418
}
1419
+
1420
+ // reset profile name
1421
+ m_profileDirName = L" " ;
1257
1422
m_documentTitle = L" " ;
1258
1423
return true ;
1259
1424
}
@@ -1371,12 +1536,17 @@ std::wstring AppWindow::GetDocumentTitle()
1371
1536
1372
1537
void AppWindow::UpdateAppTitle () {
1373
1538
std::wstring str (m_appTitle);
1539
+ if (!m_profileDirName.empty ())
1540
+ {
1541
+ str += L" - " + m_profileDirName;
1542
+ }
1374
1543
if (!m_documentTitle.empty ())
1375
1544
{
1376
1545
str += L" - " + m_documentTitle;
1377
1546
}
1378
1547
SetWindowText (m_mainWindow, str.c_str ());
1379
1548
}
1549
+
1380
1550
RECT AppWindow::GetWindowBounds ()
1381
1551
{
1382
1552
RECT hwndBounds = {0 };
0 commit comments