Skip to content

Commit

Permalink
[webview_flutter] Implement addJavascriptChannels() (#27)
Browse files Browse the repository at this point in the history
* This plugin exposes a single method called `postMessage` to JavaScript.
* This method sends a message over a method channel to the Dart code.

Signed-off-by: Seungsoo Lee <seungsoo47.lee@samsung.com>
  • Loading branch information
seungsoo47 authored Jan 29, 2021
1 parent 6a34ae0 commit 9e26386
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 24 deletions.
70 changes: 61 additions & 9 deletions packages/webview_flutter/tizen/src/webview.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

#include <Ecore_IMF_Evas.h>
#include <Ecore_Input_Evas.h>
#include <flutter/method_channel.h>
#include <flutter_platform_view.h>
#include <flutter_texture_registrar.h>

Expand Down Expand Up @@ -58,27 +57,72 @@ double ExtractDoubleFromMap(const flutter::EncodableValue& arguments,

WebView::WebView(flutter::PluginRegistrar* registrar, int viewId,
FlutterTextureRegistrar* textureRegistrar, double width,
double height, const std::string initialUrl)
double height, flutter::EncodableMap& params)
: PlatformView(registrar, viewId),
textureRegistrar_(textureRegistrar),
webViewInstance_(nullptr),
currentUrl_(initialUrl),
width_(width),
height_(height),
tbmSurface_(nullptr) {
SetTextureId(FlutterRegisterExternalTexture(textureRegistrar_));
InitWebView();
auto channel =
std::make_unique<flutter::MethodChannel<flutter::EncodableValue>>(
GetPluginRegistrar()->messenger(), GetChannelName(),
&flutter::StandardMethodCodec::GetInstance());
channel->SetMethodCallHandler(

channel_ = std::make_unique<flutter::MethodChannel<flutter::EncodableValue>>(
GetPluginRegistrar()->messenger(), GetChannelName(),
&flutter::StandardMethodCodec::GetInstance());
channel_->SetMethodCallHandler(
[webview = this](const auto& call, auto result) {
webview->HandleMethodCall(call, std::move(result));
});

auto initialUrl = params[flutter::EncodableValue("initialUrl")];
if (std::holds_alternative<std::string>(initialUrl)) {
currentUrl_ = std::get<std::string>(initialUrl);
} else {
currentUrl_ = "about:blank";
}

auto names = params[flutter::EncodableValue("javascriptChannelNames")];
if (std::holds_alternative<flutter::EncodableList>(names)) {
auto nameList = std::get<flutter::EncodableList>(names);
for (size_t i = 0; i < nameList.size(); i++) {
if (std::holds_alternative<std::string>(nameList[i])) {
RegisterJavaScriptChannelName(std::get<std::string>(nameList[i]));
}
}
}

webViewInstance_->LoadURL(currentUrl_);
}

/**
* Added as a JavaScript interface to the WebView for any JavaScript channel
* that the Dart code sets up.
*
* Exposes a single method named `postMessage` to JavaScript, which sends a
* message over a method channel to the Dart code.
*/
void WebView::RegisterJavaScriptChannelName(const std::string& name) {
LOG_DEBUG("RegisterJavaScriptChannelName(channelName: %s)\n", name.c_str());

std::function<std::string(const std::string&)> cb =
[this, name](const std::string& message) -> std::string {
LOG_DEBUG("Invoke JavaScriptChannel(message: %s)\n", message.c_str());
flutter::EncodableMap map;
map.insert(std::make_pair<flutter::EncodableValue, flutter::EncodableValue>(
flutter::EncodableValue("channel"), flutter::EncodableValue(name)));
map.insert(std::make_pair<flutter::EncodableValue, flutter::EncodableValue>(
flutter::EncodableValue("message"), flutter::EncodableValue(message)));

std::unique_ptr<flutter::EncodableValue> args =
std::make_unique<flutter::EncodableValue>(map);
channel_->InvokeMethod("javascriptChannelMessage", std::move(args));
return "success";
};

webViewInstance_->AddJavaScriptInterface(name, "postMessage", cb);
}

WebView::~WebView() { Dispose(); }

std::string WebView::GetChannelName() {
Expand Down Expand Up @@ -543,7 +587,15 @@ void WebView::HandleMethodCall(
result->Error("Invalid Arguments", "Invalid Arguments");
}
} else if (methodName.compare("addJavascriptChannels") == 0) {
result->NotImplemented();
if (std::holds_alternative<flutter::EncodableList>(arguments)) {
auto nameList = std::get<flutter::EncodableList>(arguments);
for (size_t i = 0; i < nameList.size(); i++) {
if (std::holds_alternative<std::string>(nameList[i])) {
RegisterJavaScriptChannelName(std::get<std::string>(nameList[i]));
}
}
}
result->Success();
} else if (methodName.compare("removeJavascriptChannels") == 0) {
result->NotImplemented();
} else if (methodName.compare("clearCache") == 0) {
Expand Down
7 changes: 6 additions & 1 deletion packages/webview_flutter/tizen/src/webview.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef FLUTTER_PLUGIN_WEBVIEW_FLUTTER_TIZEN_WEVIEW_H_
#define FLUTTER_PLUGIN_WEBVIEW_FLUTTER_TIZEN_WEVIEW_H_

#include <flutter/method_channel.h>
#include <flutter/plugin_registrar.h>
#include <flutter/standard_message_codec.h>
#include <flutter/standard_method_codec.h>
Expand All @@ -21,7 +22,7 @@ class WebView : public PlatformView {
public:
WebView(flutter::PluginRegistrar* registrar, int viewId,
FlutterTextureRegistrar* textureRegistrar, double width,
double height, const std::string initialUrl);
double height, flutter::EncodableMap& params);
~WebView();
virtual void Dispose() override;
virtual void Resize(double width, double height) override;
Expand All @@ -43,13 +44,17 @@ class WebView : public PlatformView {
std::string GetChannelName();
const std::string& GetCurrentUrl() { return currentUrl_; }
void InitWebView();

void RegisterJavaScriptChannelName(const std::string& name);

FlutterTextureRegistrar* textureRegistrar_;
LWE::WebContainer* webViewInstance_;
std::string currentUrl_;
double width_;
double height_;
tbm_surface_h tbmSurface_;
bool isMouseLButtonDown_;
std::unique_ptr<flutter::MethodChannel<flutter::EncodableValue>> channel_;
};

#endif // FLUTTER_PLUGIN_WEBVIEW_FLUTTER_TIZEN_WEVIEW_H_
23 changes: 9 additions & 14 deletions packages/webview_flutter/tizen/src/webview_factory.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#include "webview_factory.h"

#include <flutter/method_channel.h>
#include <flutter/plugin_registrar.h>
#include <flutter/standard_method_codec.h>
#include <flutter/standard_message_codec.h>
#include <flutter/standard_method_codec.h>
#include <flutter_platform_view.h>
#include <flutter_texture_registrar.h>

Expand All @@ -11,9 +13,8 @@
#include <string>

#include "log.h"
#include "webview_flutter_tizen_plugin.h"
#include "webview_factory.h"
#include "lwe/LWEWebView.h"
#include "webview_flutter_tizen_plugin.h"

WebViewFactory::WebViewFactory(flutter::PluginRegistrar* registrar,
FlutterTextureRegistrar* textureRegistrar)
Expand All @@ -30,19 +31,13 @@ WebViewFactory::WebViewFactory(flutter::PluginRegistrar* registrar,

PlatformView* WebViewFactory::Create(int viewId, double width, double height,
const std::vector<uint8_t>& createParams) {
std::string initialUrl = "about:blank";
auto decoded_value = *GetCodec().DecodeMessage(createParams);
if (std::holds_alternative<flutter::EncodableMap>(decoded_value)) {
flutter::EncodableMap createParams =
std::get<flutter::EncodableMap>(decoded_value);
flutter::EncodableValue initialUrlValue =
createParams[flutter::EncodableValue("initialUrl")];
if (std::holds_alternative<std::string>(initialUrlValue)) {
initialUrl = std::get<std::string>(initialUrlValue);
}
flutter::EncodableMap params;
auto decodedValue = *GetCodec().DecodeMessage(createParams);
if (std::holds_alternative<flutter::EncodableMap>(decodedValue)) {
params = std::get<flutter::EncodableMap>(decodedValue);
}
return new WebView(GetPluginRegistrar(), viewId, textureRegistrar_, width,
height, initialUrl);
height, params);
}

void WebViewFactory::Dispose() { LWE::LWE::Finalize(); }

0 comments on commit 9e26386

Please sign in to comment.