Skip to content

Commit 817ed55

Browse files
authored
Merge pull request #2214 from MicrosoftEdge/api-get-favicon
Adding new API to WebView for handling Favicons This api allows users to listen for the fav icon to change. This API has events to listen to and tools to get the icon URI.
2 parents a388a7c + 33e8678 commit 817ed55

File tree

1 file changed

+180
-0
lines changed

1 file changed

+180
-0
lines changed

specs/GetFavicon.md

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
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+
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
11+
12+
// Initialize GDI+.
13+
Gdiplus::GdiplusStartup(&gdiplusToken_, &gdiplusStartupInput, NULL);
14+
CHECK_FAILURE(m_webView2->add_FaviconChanged(
15+
Callback<ICoreWebView2FaviconChangedEventHandler>(
16+
[this](ICoreWebView2* sender, IUnknown* args) -> HRESULT {
17+
wil::unique_cotaskmem_string url;
18+
19+
CHECK_FAILURE(sender->get_FaviconUri(&url));
20+
std::wstring strUrl(url.get());
21+
if (strUrl.empty())
22+
{
23+
m_favicon.reset();
24+
SendMessage(m_appWindow->GetMainWindow(), WM_SETICON, ICON_SMALL, (LPARAM)NULL);
25+
}
26+
else
27+
{
28+
webview2->GetFavicon(
29+
COREWEBVIEW2_FAVICON_IMAGE_FORMAT_PNG,
30+
Callback<ICoreWebView2GetFaviconCompletedHandler>(
31+
[this](HRESULT errorCode, IStream* iconStream) -> HRESULT
32+
{
33+
CHECK_FAILURE(errorCode);
34+
Gdiplus::Bitmap iconBitmap(iconStream);
35+
wil::unique_hicon icon;
36+
if (iconBitmap.GetHICON(&icon) = Gdiplus::Status::Ok)
37+
{
38+
m_favicon = std::move(icon);
39+
}
40+
else
41+
{
42+
m_favicon.reset();
43+
}
44+
45+
SendMessage(
46+
m_appWindow->GetMainWindow(), WM_SETICON,
47+
ICON_SMALL, (LPARAM)m_favicon.get());
48+
return S_OK;
49+
}).Get());
50+
}
51+
return S_OK;
52+
}).Get(), &m_faviconChangedToken));
53+
}
54+
```
55+
## .NET / WinRT Registering a listener for favicon changes
56+
```c#
57+
webView.CoreWebView2.FaviconChanged += (object sender, Object arg) =>
58+
{
59+
string value = webView.CoreWebView2.FaviconUri;
60+
System.IO.Stream stream = await webView.CoreWebView2.GetFaviconAsync(
61+
CoreWebView2FaviconImageFormat.Png);
62+
if (stream == null || stream.Length == 0)
63+
this.Icon = null;
64+
else
65+
this.Icon = BitmapFrame.Create(stream);
66+
};
67+
```
68+
# API Notes
69+
Note that even if a web page does not have a Favicon and there was not a previously
70+
loaded Favicon, the event is not raised. Otherwise if there is not Favicon and the
71+
previous page did have a Favicon, the FaviconChanged event is raised when the page
72+
is navigated. The Favicon would be an empty image stream and empty Uri for the lack
73+
of a favicon. The end developer is expected to handle this scenario. Otherwise, we
74+
raise the FaviconChanged with an observed change to the Favicon. In that scenario,
75+
the CoreWebView2 has an updated value for the FaviconUri property, and the
76+
GetFavicon method to match the updated favicon. Loading the same Favicon twice does
77+
re-raise the FaviconChanged event.
78+
See [API Details](#api-details) Section below for API reference
79+
# API Details
80+
## Win32 C++
81+
```cpp
82+
/// This interface is a handler for when the `Favicon` is changed.
83+
/// The sender is the ICoreWebView2 object the top-level document of
84+
/// which has changed favicon and the eventArgs is nullptr. Use the
85+
/// FaviconUri property and GetFavicon method to obtain the favicon
86+
/// data. The second argument is always null.
87+
/// For more information see `add_FaviconChanged`.
88+
[uuid(2913DA94-833D-4DE0-8DCA-900FC524A1A4), object, pointer_default(unique)]
89+
interface ICoreWebView2FaviconChangedEventHandler : IUnknown {
90+
/// Called to notify the favicon changed.
91+
HRESULT Invoke(
92+
[in] ICoreWebView2* sender,
93+
[in] IUnknown* args);
94+
}
95+
96+
/// This interface is a handler for the completion of the population of
97+
/// `imageStream`.
98+
/// `errorCode` returns S_OK if the API succeeded.
99+
/// The image is returned in the `faviconStream` object. If there is no image
100+
/// then no data would be copied into the imageStream.
101+
/// For more details, see the `GetFavicon` API.
102+
[uuid(A2508329-7DA8-49D7-8C05-FA125E4AEE8D), object, pointer_default(unique)]
103+
interface ICoreWebView2GetFaviconCompletedHandler : IUnknown {
104+
/// Called to notify the favicon has been retrieved.
105+
HRESULT Invoke(
106+
[in] HRESULT errorCode,
107+
[in] IStream* faviconStream);
108+
}
109+
110+
/// This is the ICoreWebView2 Favicon interface.
111+
[uuid(DC838C64-F64B-4DC7-98EC-0992108E2157), object, pointer_default(unique)]
112+
interface ICoreWebView2_10 : ICoreWebView2_9 {
113+
/// Add an event handler for the `FaviconChanged` event.
114+
/// The `FaviconChanged` event is raised when the
115+
/// [favicon](https://developer.mozilla.org/en-US/docs/Glossary/Favicon)
116+
/// had a different URL then the previous URL.
117+
/// The FaviconChanged event will be raised for first navigating to a new
118+
/// document, whether or not a document declares a Favicon in HTML if the
119+
/// favicon is different from the previous fav icon. The event will
120+
/// be raised again if a favicon is declared in its HTML or has script
121+
/// to set its favicon. The favicon information can then be retrieved with
122+
/// `GetFavicon` and `FaviconUri`.
123+
HRESULT add_FaviconChanged(
124+
[in] ICoreWebView2FaviconChangedEventHandler* eventHandler,
125+
[out] EventRegistrationToken* token);
126+
127+
/// Remove the event handler for `FaviconChanged` event.
128+
HRESULT remove_FaviconChanged(
129+
[in] EventRegistrationToken token);
130+
131+
/// Get the current Uri of the favicon as a string.
132+
/// If the value is null, then the return value is `E_POINTER`, otherwise it is `S_OK`.
133+
/// If a page has no favicon then the value is an empty string.
134+
[propget] HRESULT FaviconUri([out, retval] LPWSTR* value);
135+
136+
/// Async function for getting the actual image data of the favicon.
137+
/// If the `imageStream` is null, the `HRESULT` will be `E_POINTER`, otherwise
138+
/// it is `S_OK`.
139+
/// The image is copied to the `imageStream` object. If there is no image then
140+
/// no data would be copied into the imageStream.
141+
/// In either scenario the `completedHandler` is executed at the end of the operation.
142+
HRESULT GetFavicon(
143+
[in] COREWEBVIEW2_FAVICON_IMAGE_FORMAT format,
144+
[in] IStream* imageStream,
145+
[in] ICoreWebView2GetFaviconCompletedHandler* completedHandler);
146+
}
147+
148+
[v1_enum]
149+
typedef enum COREWEBVIEW2_FAVICON_IMAGE_FORMAT {
150+
/// Indicates that CoreWebView2.GetFavicon should return the favicon in PNG format.
151+
COREWEBVIEW2_CAPTURE_PREVIEW_IMAGE_FORMAT_PNG,
152+
153+
/// Indicates that CoreWebView2.GetFavicon should return the favicon in JPG format.
154+
COREWEBVIEW2_CAPTURE_PREVIEW_IMAGE_FORMAT_JPEG,
155+
}
156+
```
157+
158+
## .Net/ WinRT
159+
```c#
160+
namespace Microsoft.Web.WebView2.Core
161+
{
162+
enum CoreWebView2FaviconImageFormat
163+
{
164+
Png = 0,
165+
Jpeg = 1,
166+
};
167+
168+
runtimeclass CoreWebView2
169+
{
170+
[interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2_10")]
171+
{
172+
String FaviconUri { get; };
173+
174+
event Windows.Foundation.TypedEventHandler<CoreWebView2, Object> FaviconChanged;
175+
176+
Windows.Foundation.IAsyncOperation<Windows.Storage.Streams.IRandomAccessStream> GetFaviconAsync(CoreWebView2FaviconImageFormat format);
177+
}
178+
}
179+
}
180+
```

0 commit comments

Comments
 (0)