22#include <wx/webview.h>
25#include <wx/filename.h>
34#if !defined(__MINGW32__)
35 #include <wrl/client.h>
36 #include <wrl/event.h>
39using Microsoft::WRL::ComPtr;
40using Microsoft::WRL::Callback;
46bool SaveCookies( wxWebView* aWebView,
const wxString& aTargetFile )
51 void* nativeBackend = aWebView->GetNativeBackend();
55#if defined(__MINGW32__)
59 ICoreWebView2* coreWebView =
static_cast<ICoreWebView2*
>( nativeBackend );
62 ComPtr<ICoreWebView2_2> webView2;
64 if( FAILED( coreWebView->QueryInterface( IID_PPV_ARGS( &webView2 ) ) ) )
66 wxLogTrace(
"webview",
"Failed to get ICoreWebView2_2 interface. WebView2 runtime might be too old." );
70 ComPtr<ICoreWebView2CookieManager> cookieManager;
72 if( FAILED( webView2->get_CookieManager( &cookieManager ) ) )
74 wxLogTrace(
"webview",
"Failed to get cookie manager" );
78 nlohmann::json cookieArray = nlohmann::json::array();
79 bool callbackFinished =
false;
82 HRESULT hr = cookieManager->GetCookies(
84 Callback<ICoreWebView2GetCookiesCompletedHandler>(
85 [&]( HRESULT
result, ICoreWebView2CookieList* list ) -> HRESULT
87 if( FAILED(
result ) || !list )
89 wxLogTrace(
"webview",
"GetCookies failed or returned null list" );
90 callbackFinished =
true;
95 list->get_Count( &count );
97 for( UINT i = 0; i < count; ++i )
99 ComPtr<ICoreWebView2Cookie> cookie;
100 if( FAILED( list->GetValueAtIndex( i, &cookie ) ) )
103 nlohmann::json cookieObj;
105 LPWSTR
name =
nullptr;
106 cookie->get_Name( &
name );
110 cookieObj[
"name"] = std::string( wxString(
name ).ToUTF8() );
111 CoTaskMemFree(
name );
114 LPWSTR value =
nullptr;
115 cookie->get_Value( &value );
119 cookieObj[
"value"] = std::string( wxString( value ).ToUTF8() );
120 CoTaskMemFree( value );
123 LPWSTR domain =
nullptr;
124 cookie->get_Domain( &domain );
128 cookieObj[
"domain"] = std::string( wxString( domain ).ToUTF8() );
129 CoTaskMemFree( domain );
132 LPWSTR
path =
nullptr;
133 cookie->get_Path( &
path );
137 cookieObj[
"path"] = std::string( wxString(
path ).ToUTF8() );
138 CoTaskMemFree(
path );
142 cookie->get_Expires( &expires );
143 cookieObj[
"expires"] =
static_cast<int64_t
>( expires );
146 cookie->get_IsSecure( &secure );
147 cookieObj[
"secure"] = ( secure == TRUE );
149 BOOL httpOnly = FALSE;
150 cookie->get_IsHttpOnly( &httpOnly );
151 cookieObj[
"httpOnly"] = ( httpOnly == TRUE );
153 cookieArray.push_back( cookieObj );
157 callbackFinished =
true;
163 wxLogTrace(
"webview",
"Failed to initiate GetCookies" );
169 long long startTime = wxGetLocalTimeMillis().GetValue();
171 while( !callbackFinished )
175 if( ( wxGetLocalTimeMillis().GetValue() - startTime ) > 5000 )
177 wxLogTrace(
"webview",
"Timeout waiting for GetCookies callback" );
189 wxFFile file( aTargetFile,
"wb" );
191 if( !file.IsOpened() )
193 wxLogTrace(
"webview",
"Failed to open cookie file for writing: %s", aTargetFile );
197 std::string jsonStr = cookieArray.dump( 2 );
198 file.Write( jsonStr.c_str(), jsonStr.size() );
205bool LoadCookies( wxWebView* aWebView,
const wxString& aSourceFile )
210 if( !wxFileName::FileExists( aSourceFile ) )
213 void* nativeBackend = aWebView->GetNativeBackend();
218#if defined(__MINGW32__)
222 ICoreWebView2* coreWebView =
static_cast<ICoreWebView2*
>( nativeBackend );
224 ComPtr<ICoreWebView2_2> webView2;
226 if( FAILED( coreWebView->QueryInterface( IID_PPV_ARGS( &webView2 ) ) ) )
228 wxLogTrace(
"webview",
"Failed to get ICoreWebView2_2 interface" );
232 ComPtr<ICoreWebView2CookieManager> cookieManager;
234 if( FAILED( webView2->get_CookieManager( &cookieManager ) ) )
236 wxLogDebug(
"Failed to get cookie manager" );
241 wxFFile file( aSourceFile,
"rb" );
243 if( !file.IsOpened() )
245 wxLogTrace(
"webview",
"Failed to open cookie file for reading: %s", aSourceFile );
249 wxFileOffset len = file.Length();
255 jsonStr.resize( len );
257 if( file.Read( &jsonStr[0], len ) != len )
259 wxLogTrace(
"webview",
"Failed to read cookie file" );
263 nlohmann::json cookieArray;
267 cookieArray = nlohmann::json::parse( jsonStr );
269 catch(
const nlohmann::json::exception& e )
271 wxLogTrace(
"webview",
"Failed to parse cookie JSON: %s", e.what() );
275 for(
const auto& cookieObj : cookieArray )
277 std::string
name = cookieObj.value(
"name",
"" );
278 std::string value = cookieObj.value(
"value",
"" );
279 std::string domain = cookieObj.value(
"domain",
"" );
280 std::string
path = cookieObj.value(
"path",
"/" );
281 bool secure = cookieObj.value(
"secure",
false );
282 bool httpOnly = cookieObj.value(
"httpOnly",
false );
283 int64_t expires = cookieObj.value(
"expires", 0 );
285 ComPtr<ICoreWebView2Cookie> cookie;
286 if( FAILED( cookieManager->CreateCookie(
287 wxString::FromUTF8(
name.c_str() ).wc_str(),
288 wxString::FromUTF8( value.c_str() ).wc_str(),
289 wxString::FromUTF8( domain.c_str() ).wc_str(),
290 wxString::FromUTF8(
path.c_str() ).wc_str(),
296 cookie->put_Expires(
static_cast<double>( expires ) );
297 cookie->put_IsSecure( secure ? TRUE : FALSE );
298 cookie->put_IsHttpOnly( httpOnly ? TRUE : FALSE );
300 cookieManager->AddOrUpdateCookie( cookie.Get() );
312 void* nativeBackend = aWebView->GetNativeBackend();
316#if defined(__MINGW32__)
320 ICoreWebView2* coreWebView =
static_cast<ICoreWebView2*
>( nativeBackend );
322 ComPtr<ICoreWebView2_2> webView2;
324 if( FAILED( coreWebView->QueryInterface( IID_PPV_ARGS( &webView2 ) ) ) )
326 wxLogTrace(
"webview",
"Failed to get ICoreWebView2_2 interface. WebView2 runtime might be too old." );
330 ComPtr<ICoreWebView2CookieManager> cookieManager;
332 if( FAILED( webView2->get_CookieManager( &cookieManager ) ) )
334 wxLogTrace(
"webview",
"Failed to get cookie manager" );
338 if( FAILED( cookieManager->DeleteAllCookies() ) )
340 wxLogTrace(
"webview",
"Failed to delete all cookies" );
wxString result
Test unit parsing edge cases and error handling.