Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[desktop-webview-window] Control URL requests made by the webview (Breaking!) #296

Merged
merged 12 commits into from
Nov 8, 2023
4 changes: 3 additions & 1 deletion packages/desktop_webview_window/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,15 @@ class _MyAppState extends State<MyApp> {
..setBrightness(Brightness.dark)
..setApplicationNameForUserAgent(" WebviewExample/1.0.0")
..launch(_controller.text)
..addOnUrlRequestCallback((url) {
..setOnUrlRequestCallback((url) {
debugPrint('url: $url');
final uri = Uri.parse(url);
if (uri.path == '/login_success') {
debugPrint('login success. token: ${uri.queryParameters['token']}');
webview.close();
}
// grant navigation request
return true;
})
..onClose.whenComplete(() {
debugPrint("on close");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,12 @@ class WebviewWindow {
break;
case "onUrlRequested":
final url = args['url'] as String;
webview.notifyUrlChanged(url);
final ret = webview.notifyUrlChanged(url);
await _otherIsolateMessageHandler.invokeMethod('onUrlRequested', {
'webViewId': viewId,
'url': url,
});
break;
return ret;
case "onWebMessageReceived":
final message = args['message'] as String;
webview.notifyWebMessageReceived(message);
Expand Down
8 changes: 3 additions & 5 deletions packages/desktop_webview_window/lib/src/webview.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ typedef OnHistoryChangedCallback = void Function(

/// Callback when WebView start to load a URL.
/// [url] is the URL string.
typedef OnUrlRequestCallback = void Function(String url);
typedef OnUrlRequestCallback = bool Function(String url);

/// Callback when WebView receives a web message
/// [message] constains the webmessage
Expand All @@ -35,7 +35,7 @@ abstract class Webview {
void setPromptHandler(PromptHandler? handler);

/// Navigates to the given URL.
void launch(String url);
void launch(String url, {bool triggerOnUrlRequestEvent=true});

/// change webview theme.
///
Expand Down Expand Up @@ -74,9 +74,7 @@ abstract class Webview {
/// Register a callback that will be invoked when the webview history changes.
void setOnHistoryChangedCallback(OnHistoryChangedCallback? callback);

void addOnUrlRequestCallback(OnUrlRequestCallback callback);

void removeOnUrlRequestCallback(OnUrlRequestCallback callback);
void setOnUrlRequestCallback(OnUrlRequestCallback? callback);

void addOnWebMessageReceivedCallback(OnWebMessageReceivedCallback callback);

Expand Down
30 changes: 14 additions & 16 deletions packages/desktop_webview_window/lib/src/webview_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ class WebviewImpl extends Webview {

OnHistoryChangedCallback? _onHistoryChanged;

final ValueNotifier<bool> _isNaivgating = ValueNotifier<bool>(false);
final ValueNotifier<bool> _isNavigating = ValueNotifier<bool>(false);

final Set<OnUrlRequestCallback> _onUrlRequestCallbacks = {};
OnUrlRequestCallback? _onUrlRequestCallback = null;

final Set<OnWebMessageReceivedCallback> _onWebMessageReceivedCallbacks = {};

Expand Down Expand Up @@ -57,12 +57,14 @@ class WebviewImpl extends Webview {
}

void onNavigationStarted() {
_isNaivgating.value = true;
_isNavigating.value = true;
}

void notifyUrlChanged(String url) {
for (final callback in _onUrlRequestCallbacks) {
callback(url);
bool notifyUrlChanged(String url) {
if(_onUrlRequestCallback != null) {
return _onUrlRequestCallback!(url);
} else {
return true;
}
}

Expand All @@ -73,11 +75,11 @@ class WebviewImpl extends Webview {
}

void onNavigationCompleted() {
_isNaivgating.value = false;
_isNavigating.value = false;
}

@override
ValueListenable<bool> get isNavigating => _isNaivgating;
ValueListenable<bool> get isNavigating => _isNavigating;

@override
void registerJavaScriptMessageHandler(
Expand Down Expand Up @@ -121,10 +123,11 @@ class WebviewImpl extends Webview {
}

@override
void launch(String url) async {
void launch(String url, {bool triggerOnUrlRequestEvent=true}) async {
await channel.invokeMethod("launch", {
"url": url,
"viewId": viewId,
"triggerOnUrlRequestEvent": triggerOnUrlRequestEvent,
});
}

Expand Down Expand Up @@ -223,13 +226,8 @@ class WebviewImpl extends Webview {
}

@override
void addOnUrlRequestCallback(OnUrlRequestCallback callback) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the callbackparameter should be nullable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

_onUrlRequestCallbacks.add(callback);
}

@override
void removeOnUrlRequestCallback(OnUrlRequestCallback callback) {
_onUrlRequestCallbacks.remove(callback);
void setOnUrlRequestCallback(OnUrlRequestCallback? callback) {
_onUrlRequestCallback = callback;
}

@override
Expand Down
42 changes: 34 additions & 8 deletions packages/desktop_webview_window/windows/web_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <utility>
#include <thread>

#include "flutter/method_result_functions.h"

#include "web_view.h"
#include "utils.h"
#include "strconv.h"
Expand Down Expand Up @@ -144,14 +146,34 @@ void WebView::OnWebviewControllerCreated() {
std::make_unique<flutter::EncodableValue>(flutter::EncodableMap{
{flutter::EncodableValue("id"), flutter::EncodableValue(web_view_id_)},
}));
LPWSTR uri;
args->get_Uri(&uri);
method_channel_->InvokeMethod(
"onUrlRequested",
std::make_unique<flutter::EncodableValue>(flutter::EncodableMap{
{flutter::EncodableValue("id"), flutter::EncodableValue(web_view_id_)},
{flutter::EncodableValue("url"), flutter::EncodableValue(wide_to_utf8(std::wstring(uri)))},
}));

if (triggerOnUrlRequestedEvent) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary? It should make more sense to trigger onUrlRequest on any request (including from navigate(String) method).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion its more convenient like this, because otherwise the call of "webview.launch(url)" would trigger the OnUrlRequest event every time and you manually had to grant it every time. If you call "webview.launch(url)" you know already that the webview will navigate to the url now, because you requested it yourself. But I am more interested in navigations triggered by the webview itself.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I can also make it, that also "webview.launch(url)" triggers the event. How would you like to have it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry for later.

But I still stand by my opinion.

for example:
If you need to display the currently requested URL in the console or elsewhere, you only need to add a callback instead of adding code in various places.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok seems also reasonable. Then I suggest to add an optional parameter with default value to webview.launch:
webview.launch(..., triggerOnUrlRequestEvent=true)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a new commit containing the additional parameter for webview.launch

Please review

LPWSTR uri;
args->get_Uri(&uri);

auto result_handler = std::make_unique<flutter::MethodResultFunctions<>>(
[uri, sender, this](const flutter::EncodableValue* success_value) {
const bool letPass = std::get<bool>(*success_value);
if (letPass) {
this->setTriggerOnUrlRequestedEvent(false);
sender->Navigate(uri);
}
},
nullptr, nullptr);

method_channel_->InvokeMethod(
"onUrlRequested",
std::make_unique<flutter::EncodableValue>(flutter::EncodableMap{
{flutter::EncodableValue("id"), flutter::EncodableValue(web_view_id_)},
{flutter::EncodableValue("url"), flutter::EncodableValue(wide_to_utf8(std::wstring(uri)))},
}), std::move(result_handler));

// navigation is canceled here and retriggered later from the callback passed to the method channel
args->put_Cancel(true);
} else {
args->put_Cancel(false);
triggerOnUrlRequestedEvent = true;
}
return S_OK;
}
).Get(), nullptr);
Expand Down Expand Up @@ -323,6 +345,10 @@ void WebView::PostWebMessageAsJson(const std::wstring& webmessage,
}
}

void WebView::setTriggerOnUrlRequestedEvent(const bool value) {
this->triggerOnUrlRequestedEvent = value;
}

WebView::~WebView() {
if (webview_) {
webview_->Stop();
Expand Down
4 changes: 4 additions & 0 deletions packages/desktop_webview_window/windows/web_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ class WebView {
void PostWebMessageAsJson(const std::wstring &webmessage,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> completer);

void setTriggerOnUrlRequestedEvent(const bool value);

private:
wil::unique_hwnd view_window_;

Expand All @@ -79,6 +81,8 @@ class WebView {

std::wstring user_data_folder_;

bool triggerOnUrlRequestedEvent{true};

void OnWebviewControllerCreated();

[[nodiscard]] bool CanGoBack() const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ void WebviewWindowPlugin::HandleMethodCall(

auto window_id = arguments->at(flutter::EncodableValue("viewId")).LongValue();
auto url = std::get<std::string>(arguments->at(flutter::EncodableValue("url")));
auto triggerOnUrlRequestEvent = std::get<bool>(arguments->at(flutter::EncodableValue("triggerOnUrlRequestEvent")));

if (!windows_.count(window_id)) {
result->Error("0", "can not find webview window for id");
Expand All @@ -95,6 +96,7 @@ void WebviewWindowPlugin::HandleMethodCall(
result->Error("0", "webview window not ready");
return;
}
windows_[window_id]->GetWebView()->setTriggerOnUrlRequestedEvent(triggerOnUrlRequestEvent);
windows_[window_id]->GetWebView()->Navigate(utf8_to_wide(url));
result->Success();
} else if (method_call.method_name() == "addScriptToExecuteOnDocumentCreated") {
Expand Down