|
| 1 | +# Background |
| 2 | +A favicon (favorite icon) is a tiny icon included along with a website, which is displayed in places like the browser's address bar, page tabs and bookmarks menu. Developers would like to have an API which allows them to retrieve the Favicon of a webpage, if it has been set, as well as get an update whenever the favicon has changed. |
| 3 | + |
| 4 | +# Description |
| 5 | +We propose a new Webview2 event which would allow developers to access the current Favicon of a page and be notified when the favicon changes. This means when a page first loads, it would raise the FaviconChanged event since before parsing the HTML document there is no known favicon. DOM or JavaScript may change the Favicon, causing the event to be raised again for the same document. |
| 6 | + |
| 7 | +# Examples |
| 8 | +## Win32 C++ Registering a listener for favicon changes |
| 9 | +```cpp |
| 10 | +CHECK_FAILURE(m_webView->add_FaviconChanged( |
| 11 | + Callback<ICoreWebView2FaviconChangedEventHandler>( |
| 12 | + [this](ICoreWebView2* sender, IUnknown* args) -> HRESULT { |
| 13 | + |
| 14 | + wil::com_ptr<IStream> iconStream = SHCreateMemStream(nullptr, 0); |
| 15 | + |
| 16 | + sender->GetFavicon(COREWEBVIEW2_FAVICON_IMAGE_FORMAT_PNG, iconStream.get(), |
| 17 | + Callback<ICoreWebView2ExperimentalGetFaviconCompletedHandler>( |
| 18 | + [iconStream, this](HRESULT error_code) -> HRESULT |
| 19 | + { |
| 20 | + if (error_code == S_OK) |
| 21 | + { |
| 22 | + Gdiplus::Bitmap* iconBitmap = |
| 23 | + new Gdiplus::Bitmap(iconStream.get()); |
| 24 | + HICON icon; |
| 25 | + if (!iconBitmap->GetHICON(&icon)) |
| 26 | + { |
| 27 | + SendMessage( |
| 28 | + m_appWindow->GetMainWindow(), WM_SETICON, |
| 29 | + ICON_SMALL, (LPARAM)icon); |
| 30 | + } |
| 31 | + } |
| 32 | + |
| 33 | + return S_OK; |
| 34 | + }).Get()); |
| 35 | + |
| 36 | + return S_OK; |
| 37 | + }).Get(), &m_faviconChangedToken)); |
| 38 | +``` |
| 39 | +## .NET / WinRT Registering a listener for favicon changes |
| 40 | +```c# |
| 41 | +webView.CoreWebView2.FaviconChanged += (CoreWebView2 sender, Object arg) => |
| 42 | +{ |
| 43 | + System.IO.Stream stream = new System.IO.MemoryStream(); |
| 44 | + await webView.CoreWebView2.GetFaviconAsync( |
| 45 | + CoreWebView2FaviconImageFormat.Png, |
| 46 | + stream); |
| 47 | + // setting the window Icon to the bitmap |
| 48 | + this.Icon = BitmapFrame.Create(stream); |
| 49 | +
|
| 50 | +}; |
| 51 | +``` |
| 52 | +# API Notes |
| 53 | +Note that even if a web page does not have a Favicon, the FaviconChanged event |
| 54 | +is raised when the page is navigated to. The Favicon would be an |
| 55 | +empty image stream and empty Uri for the lack of a favicon. The end developer is expected to handle this scenario. |
| 56 | +Otherwise, we raise the FaviconChanged with an observed change to the |
| 57 | +Favicon. In that scenario, the CoreWebView2 has an updated value for the FaviconUri property, and the GetFavicon method to match the updated favicon. |
| 58 | +See [API Details](#api-details) Section below for API reference |
| 59 | +# API Details |
| 60 | +## Win32 C++ |
| 61 | +```cpp |
| 62 | +/// This interface is a handler for when the `Favicon` is changed. |
| 63 | +/// The sender is the ICoreWebView2 object the top-level document of |
| 64 | +/// which has changed favicon and the eventArgs is nullptr. Use the |
| 65 | +/// FaviconUri property and GetFavicon method to obtain the favicon |
| 66 | +/// data. The second argument is always null. |
| 67 | +/// For more information see `add_FaviconChanged`. |
| 68 | +[uuid(2913DA94-833D-4DE0-8DCA-900FC524A1A4), object, pointer_default(unique)] |
| 69 | +interface ICoreWebView2FaviconChangedEventHandler : IUnknown { |
| 70 | + /// Called to notify the favicon changed. |
| 71 | + HRESULT Invoke( |
| 72 | + [in] ICoreWebView2* sender, |
| 73 | + [in] IUnknown* args); |
| 74 | +} |
| 75 | + |
| 76 | +/// This interface is a handler for the completion of the copying for the`imageStream`. |
| 77 | +/// The 'error_code` is E_NOT_SET if the there is no image. Otherwise error_code |
| 78 | +/// is the result from the image write operation. |
| 79 | +/// For more details, see the `GetFavicon` API. |
| 80 | +[uuid(A2508329-7DA8-49D7-8C05-FA125E4AEE8D), object, pointer_default(unique)] |
| 81 | +interface ICoreWebView2GetFaviconCompletedHandler : IUnknown { |
| 82 | + /// Called to notify the favicon has been retrieved. |
| 83 | + HRESULT Invoke([in] HRESULT error_code); |
| 84 | +} |
| 85 | + |
| 86 | +/// This is the ICoreWebView2 Experimental Favicon interface. |
| 87 | +[uuid(DC838C64-F64B-4DC7-98EC-0992108E2157), object, pointer_default(unique)] |
| 88 | +interface ICoreWebView2_10 : ICoreWebView2_9 { |
| 89 | + /// Add an event handler for the `FaviconChanged` event. |
| 90 | + /// The `FaviconChanged` event is raised when the |
| 91 | + /// [favicon](https://developer.mozilla.org/en-US/docs/Glossary/Favicon) |
| 92 | + /// of the top-level document changes or if script dynamically changes the favicon. |
| 93 | + /// The FaviconChanged event will be raised for first navigating to a new |
| 94 | + /// document, whether or not a document declares a Favicon in HTML. The event will |
| 95 | + /// be raised again if a favicon is declared in its HTML or has script |
| 96 | + /// to set its favicon. The favicon information can then be retrieved with |
| 97 | + /// `GetFavicon` and `FaviconUri`. |
| 98 | + HRESULT add_FaviconChanged( |
| 99 | + [in] ICoreWebViewFaviconChangedEventHandler* eventHandler, |
| 100 | + [out] EventRegistrationToken* token); |
| 101 | + |
| 102 | + /// Remove the event handler for `FaviconChanged` event. |
| 103 | + HRESULT remove_FaviconChanged( |
| 104 | + [in] EventRegistrationToken token); |
| 105 | + |
| 106 | + /// Get the current Uri of the favicon as a string. |
| 107 | + /// If the value is null, then the return value is `E_POINTER`, otherwise it is `S_OK`. |
| 108 | + /// If a page has no favicon then the value is an empty string. |
| 109 | + [propget] HRESULT FaviconUri([out, retval] LPWSTR* value); |
| 110 | + |
| 111 | + /// Async function for getting the actual image data of the favicon. |
| 112 | + /// If the `imageStream` is null, the `HRESULT` will be `E_POINTER`, otherwise |
| 113 | + /// it is `S_OK`. |
| 114 | + /// The image is copied to the `imageStream` object. If there is no image then |
| 115 | + /// no data would be copied into the imageStream. |
| 116 | + /// In either scenario the `completedHandler` is executed at the end of the operation. |
| 117 | + HRESULT GetFavicon( |
| 118 | + [in] COREWEBVIEW2_FAVICON_IMAGE_FORMAT format, |
| 119 | + [in] IStream* imageStream, |
| 120 | + [in] ICoreWebView2GetFaviconCompletedHandler* completedHandler); |
| 121 | +} |
| 122 | + |
| 123 | +[v1_enum] |
| 124 | +typedef enum COREWEBVIEW2_FAVICON_IMAGE_FORMAT { |
| 125 | + /// Indicates that CoreWebView2.GetFaviconAsync should return the favicon in PNG format. |
| 126 | + COREWEBVIEW2_CAPTURE_PREVIEW_IMAGE_FORMAT_PNG, |
| 127 | + |
| 128 | + /// Indicates that CoreWebView2.GetFaviconAsync should return the favicon in JPG format. |
| 129 | + COREWEBVIEW2_CAPTURE_PREVIEW_IMAGE_FORMAT_JPEG, |
| 130 | +} |
| 131 | +``` |
| 132 | + |
| 133 | +## .Net/ WinRT |
| 134 | +```c# |
| 135 | +namespace Microsoft.Web.WebView2.Core |
| 136 | +{ |
| 137 | + enum CoreWebView2FaviconImageFormat |
| 138 | + { |
| 139 | + Png = 0, |
| 140 | + Jpeg = 1, |
| 141 | + }; |
| 142 | + |
| 143 | + runtimeclass CoreWebView2 |
| 144 | + { |
| 145 | + [interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2_10")] |
| 146 | + { |
| 147 | + String FaviconUri { get; }; |
| 148 | + |
| 149 | + event Windows.Foundation.TypedEventHandler<CoreWebView2, Object> FaviconChanged; |
| 150 | + |
| 151 | + Windows.Foundation.IAsyncAction GetFaviconAsync(CoreWebView2FaviconImageFormat format, Windows.Storage.Streams.IRandomAccessStream imageStream); |
| 152 | + } |
| 153 | + } |
| 154 | +} |
| 155 | +``` |
0 commit comments