|
| 1 | +// Copyright (C) Microsoft Corporation. All rights reserved. |
| 2 | +// Use of this source code is governed by a BSD-style license that can be |
| 3 | +// found in the LICENSE file. |
| 4 | + |
| 5 | +#include "stdafx.h" |
| 6 | + |
| 7 | +#include "ScenarioCookieManagement.h" |
| 8 | + |
| 9 | +#include "AppWindow.h" |
| 10 | +#include "CheckFailure.h" |
| 11 | +#include <ctime> |
| 12 | +#include <regex> |
| 13 | + |
| 14 | +using namespace Microsoft::WRL; |
| 15 | + |
| 16 | +static constexpr WCHAR c_samplePath[] = L"ScenarioCookieManagement.html"; |
| 17 | + |
| 18 | +ScenarioCookieManagement::ScenarioCookieManagement(AppWindow* appWindow) |
| 19 | + : m_appWindow(appWindow), m_webView(appWindow->GetWebView()) |
| 20 | +{ |
| 21 | + m_sampleUri = m_appWindow->GetLocalUri(c_samplePath); |
| 22 | + |
| 23 | + ComPtr<ICoreWebView2Settings> settings; |
| 24 | + CHECK_FAILURE(m_webView->get_Settings(&settings)); |
| 25 | + CHECK_FAILURE(settings->put_IsWebMessageEnabled(TRUE)); |
| 26 | + |
| 27 | + //! [CookieManager] |
| 28 | + m_webViewExperimental = m_webView.query<ICoreWebView2Experimental>(); |
| 29 | + CHECK_FAILURE(m_webViewExperimental->get_CookieManager(&m_cookieManager)); |
| 30 | + //! [CookieManager] |
| 31 | + |
| 32 | + // Setup the web message received event handler before navigating to |
| 33 | + // ensure we don't miss any messages. |
| 34 | + CHECK_FAILURE(m_webView->add_WebMessageReceived( |
| 35 | + Microsoft::WRL::Callback<ICoreWebView2WebMessageReceivedEventHandler>( |
| 36 | + [this](ICoreWebView2* sender, ICoreWebView2WebMessageReceivedEventArgs* args) { |
| 37 | + wil::unique_cotaskmem_string uri; |
| 38 | + CHECK_FAILURE(args->get_Source(&uri)); |
| 39 | + |
| 40 | + // Always validate that the origin of the message is what you expect. |
| 41 | + if (uri.get() != m_sampleUri) |
| 42 | + { |
| 43 | + return S_OK; |
| 44 | + } |
| 45 | + wil::unique_cotaskmem_string messageRaw; |
| 46 | + CHECK_FAILURE(args->TryGetWebMessageAsString(&messageRaw)); |
| 47 | + std::wstring message = messageRaw.get(); |
| 48 | + std::wstring reply; |
| 49 | + |
| 50 | + if (message.compare(0, 11, L"GetCookies ") == 0) |
| 51 | + { |
| 52 | + std::wstring uri; |
| 53 | + if (message.length() != 11) |
| 54 | + { |
| 55 | + uri = message.substr(11); |
| 56 | + } |
| 57 | + GetCookiesHelper(uri.c_str()); |
| 58 | + } |
| 59 | + else if (message.compare(0, 17, L"AddOrUpdateCookie") == 0) |
| 60 | + { |
| 61 | + //! [AddOrUpdateCookie] |
| 62 | + wil::com_ptr<ICoreWebView2ExperimentalCookie> cookie; |
| 63 | + CHECK_FAILURE(m_cookieManager->CreateCookie( |
| 64 | + L"CookieName", L"CookieValue", L".bing.com", L"/", &cookie)); |
| 65 | + CHECK_FAILURE(m_cookieManager->AddOrUpdateCookie(cookie.get())); |
| 66 | + //! [AddOrUpdateCookie] |
| 67 | + } |
| 68 | + else if (message.compare(0, 16, L"DeleteAllCookies") == 0) |
| 69 | + { |
| 70 | + CHECK_FAILURE(m_cookieManager->DeleteAllCookies()); |
| 71 | + } |
| 72 | + return S_OK; |
| 73 | + }) |
| 74 | + .Get(), |
| 75 | + &m_webMessageReceivedToken)); |
| 76 | + |
| 77 | + // Turn off this scenario if we navigate away from the sample page |
| 78 | + CHECK_FAILURE(m_webView->add_ContentLoading( |
| 79 | + Callback<ICoreWebView2ContentLoadingEventHandler>( |
| 80 | + [this]( |
| 81 | + ICoreWebView2* sender, ICoreWebView2ContentLoadingEventArgs* args) -> HRESULT { |
| 82 | + wil::unique_cotaskmem_string uri; |
| 83 | + sender->get_Source(&uri); |
| 84 | + if (uri.get() != m_sampleUri) |
| 85 | + { |
| 86 | + m_appWindow->DeleteComponent(this); |
| 87 | + } |
| 88 | + return S_OK; |
| 89 | + }) |
| 90 | + .Get(), |
| 91 | + &m_contentLoadingToken)); |
| 92 | + |
| 93 | + CHECK_FAILURE(m_webView->Navigate(m_sampleUri.c_str())); |
| 94 | +} |
| 95 | + |
| 96 | +ScenarioCookieManagement::~ScenarioCookieManagement() |
| 97 | +{ |
| 98 | + m_webView->remove_WebMessageReceived(m_webMessageReceivedToken); |
| 99 | + m_webView->remove_ContentLoading(m_contentLoadingToken); |
| 100 | +} |
| 101 | + |
| 102 | +static std::wstring BoolToString(BOOL value) |
| 103 | +{ |
| 104 | + return value ? L"true" : L"false"; |
| 105 | +} |
| 106 | + |
| 107 | +static std::wstring EncodeQuote(std::wstring raw) |
| 108 | +{ |
| 109 | + return L"\"" + regex_replace(raw, std::wregex(L"\""), L"\\\"") + L"\""; |
| 110 | +} |
| 111 | + |
| 112 | +static std::wstring SecondsToString(UINT32 time) |
| 113 | +{ |
| 114 | + WCHAR rawResult[26]; |
| 115 | + time_t rawTime; |
| 116 | + rawTime = (const time_t)time; |
| 117 | + struct tm timeStruct; |
| 118 | + gmtime_s(&timeStruct, &rawTime); |
| 119 | + _wasctime_s(rawResult, 26, &timeStruct); |
| 120 | + std::wstring result(rawResult); |
| 121 | + return result; |
| 122 | +} |
| 123 | + |
| 124 | +static std::wstring CookieToString(ICoreWebView2ExperimentalCookie* cookie) |
| 125 | +{ |
| 126 | + //! [CookieObject] |
| 127 | + wil::unique_cotaskmem_string name; |
| 128 | + CHECK_FAILURE(cookie->get_Name(&name)); |
| 129 | + wil::unique_cotaskmem_string value; |
| 130 | + CHECK_FAILURE(cookie->get_Value(&value)); |
| 131 | + wil::unique_cotaskmem_string domain; |
| 132 | + CHECK_FAILURE(cookie->get_Domain(&domain)); |
| 133 | + wil::unique_cotaskmem_string path; |
| 134 | + CHECK_FAILURE(cookie->get_Path(&path)); |
| 135 | + double expires; |
| 136 | + CHECK_FAILURE(cookie->get_Expires(&expires)); |
| 137 | + BOOL isHttpOnly = FALSE; |
| 138 | + CHECK_FAILURE(cookie->get_IsHttpOnly(&isHttpOnly)); |
| 139 | + COREWEBVIEW2_COOKIE_SAME_SITE_KIND same_site; |
| 140 | + std::wstring same_site_as_string; |
| 141 | + CHECK_FAILURE(cookie->get_SameSite(&same_site)); |
| 142 | + switch (same_site) |
| 143 | + { |
| 144 | + case COREWEBVIEW2_COOKIE_SAME_SITE_KIND_NONE: |
| 145 | + same_site_as_string = L"None"; |
| 146 | + break; |
| 147 | + case COREWEBVIEW2_COOKIE_SAME_SITE_KIND_LAX: |
| 148 | + same_site_as_string = L"Lax"; |
| 149 | + break; |
| 150 | + case COREWEBVIEW2_COOKIE_SAME_SITE_KIND_STRICT: |
| 151 | + same_site_as_string = L"Strict"; |
| 152 | + break; |
| 153 | + } |
| 154 | + BOOL isSecure = FALSE; |
| 155 | + CHECK_FAILURE(cookie->get_IsSecure(&isSecure)); |
| 156 | + BOOL isSession = FALSE; |
| 157 | + CHECK_FAILURE(cookie->get_IsSession(&isSession)); |
| 158 | + |
| 159 | + std::wstring result = L"{"; |
| 160 | + result += L"\"Name\": " + EncodeQuote(name.get()) + L", " + L"\"Value\": " + |
| 161 | + EncodeQuote(value.get()) + L", " + L"\"Domain\": " + EncodeQuote(domain.get()) + |
| 162 | + L", " + L"\"Path\": " + EncodeQuote(path.get()) + L", " + L"\"HttpOnly\": " + |
| 163 | + BoolToString(isHttpOnly) + L", " + L"\"Secure\": " + BoolToString(isSecure) + L", " + |
| 164 | + L"\"SameSite\": " + EncodeQuote(same_site_as_string) + L", " + L"\"Expires\": "; |
| 165 | + if (!!isSession) |
| 166 | + { |
| 167 | + result += L"This is a session cookie."; |
| 168 | + } |
| 169 | + else |
| 170 | + { |
| 171 | + result += std::to_wstring(expires); |
| 172 | + } |
| 173 | + |
| 174 | + return result + L"\"}"; |
| 175 | + //! [CookieObject] |
| 176 | +} |
| 177 | + |
| 178 | +void ScenarioCookieManagement::GetCookiesHelper(std::wstring uri) |
| 179 | +{ |
| 180 | + //! [GetCookies] |
| 181 | + if (m_cookieManager) |
| 182 | + { |
| 183 | + CHECK_FAILURE(m_cookieManager->GetCookies( |
| 184 | + uri.c_str(), |
| 185 | + Callback<ICoreWebView2ExperimentalGetCookiesCompletedHandler>( |
| 186 | + [this, uri](HRESULT error_code, ICoreWebView2ExperimentalCookieList* list) -> HRESULT { |
| 187 | + CHECK_FAILURE(error_code); |
| 188 | + |
| 189 | + std::wstring result; |
| 190 | + UINT cookie_list_size; |
| 191 | + CHECK_FAILURE(list->get_Count(&cookie_list_size)); |
| 192 | + |
| 193 | + if (cookie_list_size == 0) |
| 194 | + { |
| 195 | + result += L"No cookies found."; |
| 196 | + } |
| 197 | + else |
| 198 | + { |
| 199 | + result += std::to_wstring(cookie_list_size) + L" cookie(s) found"; |
| 200 | + if (!uri.empty()) |
| 201 | + { |
| 202 | + result += L" on " + uri; |
| 203 | + } |
| 204 | + result += L"\n\n["; |
| 205 | + for (int i = 0; i < cookie_list_size; ++i) |
| 206 | + { |
| 207 | + wil::com_ptr<ICoreWebView2ExperimentalCookie> cookie; |
| 208 | + CHECK_FAILURE(list->GetValueAtIndex(i, &cookie)); |
| 209 | + |
| 210 | + if (cookie.get()) |
| 211 | + { |
| 212 | + result += CookieToString(cookie.get()); |
| 213 | + if (i != cookie_list_size - 1) |
| 214 | + { |
| 215 | + result += L",\n"; |
| 216 | + } |
| 217 | + } |
| 218 | + } |
| 219 | + result += L"]"; |
| 220 | + } |
| 221 | + MessageBox(nullptr, result.c_str(), L"GetCookies Result", MB_OK); |
| 222 | + return S_OK; |
| 223 | + }) |
| 224 | + .Get())); |
| 225 | + } |
| 226 | + //! [GetCookies] |
| 227 | +} |
0 commit comments