Skip to content

Commit ff9486d

Browse files
committed
Implement TizenAutofill
1 parent c959aa0 commit ff9486d

File tree

6 files changed

+323
-1
lines changed

6 files changed

+323
-1
lines changed

flutter/shell/platform/tizen/channels/text_input_channel.cc

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
#include "flutter/shell/platform/tizen/flutter_tizen_engine.h"
99
#include "flutter/shell/platform/tizen/logger.h"
1010

11+
#ifdef AUTOFILL_SUPPORT
12+
#include "flutter/shell/platform/tizen/tizen_autofill.h"
13+
#endif
14+
1115
namespace flutter {
1216

1317
namespace {
@@ -42,6 +46,11 @@ constexpr char kTextKey[] = "text";
4246
constexpr char kBadArgumentError[] = "Bad Arguments";
4347
constexpr char kInternalConsistencyError[] = "Internal Consistency Error";
4448

49+
constexpr char kRequestAutofillMethod[] = "TextInput.requestAutofill";
50+
constexpr char kAutofill[] = "autofill";
51+
constexpr char kUniqueIdentifier[] = "uniqueIdentifier";
52+
constexpr char kHints[] = "hints";
53+
4554
bool IsAsciiPrintableKey(char ch) {
4655
return ch >= 32 && ch <= 126;
4756
}
@@ -61,6 +70,10 @@ TextInputChannel::TextInputChannel(
6170
std::unique_ptr<MethodResult<rapidjson::Document>> result) {
6271
HandleMethodCall(call, std::move(result));
6372
});
73+
TizenAutofill& instance = TizenAutofill::GetInstance();
74+
instance.SetPopupCallback(
75+
[this]() { input_method_context_->PopupAutofillItems(); });
76+
instance.SetCommitCallback([this](std::string value) { OnCommit(value); });
6477
}
6578

6679
TextInputChannel::~TextInputChannel() {}
@@ -222,6 +235,27 @@ void TextInputChannel::HandleMethodCall(
222235
}
223236
}
224237

238+
auto autofill_iter = client_config.FindMember(kAutofill);
239+
if (autofill_iter != client_config.MemberEnd() &&
240+
autofill_iter->value.IsObject()) {
241+
auto unique_identifier_iter =
242+
autofill_iter->value.FindMember(kUniqueIdentifier);
243+
if (unique_identifier_iter != autofill_iter->value.MemberEnd() &&
244+
unique_identifier_iter->value.IsString()) {
245+
autofill_id_ = unique_identifier_iter->value.GetString();
246+
}
247+
248+
auto hints_iter = autofill_iter->value.FindMember(kHints);
249+
if (hints_iter != autofill_iter->value.MemberEnd() &&
250+
hints_iter->value.IsArray()) {
251+
for (auto hint = hints_iter->value.GetArray().Begin();
252+
hint != hints_iter->value.GetArray().End(); hint++) {
253+
autofill_hints_.clear();
254+
autofill_hints_.push_back(hint->GetString());
255+
}
256+
}
257+
}
258+
225259
active_model_ = std::make_unique<TextInputModel>();
226260
} else if (method.compare(kSetEditingStateMethod) == 0) {
227261
input_method_context_->ResetInputMethodContext();
@@ -284,6 +318,11 @@ void TextInputChannel::HandleMethodCall(
284318
cursor_offset);
285319
}
286320
SendStateUpdate();
321+
#ifdef AUTOFILL_SUPPORT
322+
} else if (method.compare(kRequestAutofillMethod) == 0) {
323+
TizenAutofill& instance = TizenAutofill::GetInstance();
324+
instance.RequestAutofill(autofill_hints_, autofill_id_);
325+
#endif
287326
} else {
288327
result->NotImplemented();
289328
return;

flutter/shell/platform/tizen/channels/text_input_channel.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <memory>
99
#include <string>
10+
#include <vector>
1011

1112
#include "flutter/shell/platform/common/client_wrapper/include/flutter/binary_messenger.h"
1213
#include "flutter/shell/platform/common/client_wrapper/include/flutter/method_channel.h"
@@ -79,6 +80,10 @@ class TextInputChannel {
7980
// Automatic text capitalization type. See available options:
8081
// https://api.flutter.dev/flutter/services/TextCapitalization.html
8182
std::string text_capitalization_ = "";
83+
84+
std::string autofill_id_;
85+
86+
std::vector<std::string> autofill_hints_;
8287
};
8388

8489
} // namespace flutter
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
// Copyright 2023 Samsung Electronics Co., Ltd. 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 "flutter/shell/platform/tizen/tizen_autofill.h"
6+
7+
#include <app_common.h>
8+
#include <autofill_common.h>
9+
10+
#include <functional>
11+
#include <memory>
12+
13+
#include "flutter/shell/platform/tizen/logger.h"
14+
15+
TizenAutofill::TizenAutofill() {
16+
InitailizeAutofill();
17+
}
18+
19+
TizenAutofill::~TizenAutofill() {
20+
autofill_destroy(ah_);
21+
}
22+
23+
void TizenAutofill::InitailizeAutofill() {
24+
autofill_create(&ah_);
25+
26+
int ret;
27+
ret = autofill_connect(
28+
ah_,
29+
[](autofill_h ah, autofill_connection_status_e status, void* user_data) {
30+
},
31+
NULL);
32+
if (ret != AUTOFILL_ERROR_NONE) {
33+
FT_LOG(Error) << __FUNCTION__ << "connect_autofill_daemon error";
34+
}
35+
36+
autofill_fill_response_set_received_cb(
37+
ah_,
38+
[](autofill_h ah, autofill_fill_response_h fill_response, void* data) {
39+
int count = 0;
40+
autofill_fill_response_get_group_count(fill_response, &count);
41+
autofill_fill_response_foreach_group(
42+
fill_response,
43+
[](autofill_fill_response_group_h group_h, void* user_data) {
44+
autofill_fill_response_group_foreach_item(
45+
group_h,
46+
[](autofill_fill_response_item_h item, void* user_data) {
47+
char* id = nullptr;
48+
char* value = nullptr;
49+
char* presentation_text = nullptr;
50+
51+
autofill_fill_response_item_get_id(item, &id);
52+
autofill_fill_response_item_get_presentation_text(
53+
item, &presentation_text);
54+
autofill_fill_response_item_get_value(item, &value);
55+
56+
std::unique_ptr<AutofillItem> response_item =
57+
std::make_unique<AutofillItem>();
58+
response_item->label_ = std::string(presentation_text);
59+
response_item->id_ = std::string(id);
60+
response_item->value_ = std::string(value);
61+
62+
TizenAutofill::GetInstance().StoreResponseItem(
63+
move(response_item));
64+
65+
if (id) {
66+
free(id);
67+
}
68+
69+
if (value) {
70+
free(value);
71+
}
72+
73+
if (presentation_text) {
74+
free(presentation_text);
75+
}
76+
77+
return true;
78+
},
79+
group_h);
80+
return true;
81+
},
82+
&count);
83+
TizenAutofill::GetInstance().CallPopupCallback();
84+
},
85+
nullptr);
86+
87+
response_items_.clear();
88+
}
89+
90+
void TizenAutofill::RequestAutofill(std::vector<std::string> hints,
91+
std::string id) {
92+
char* app_id = nullptr;
93+
app_get_id(&app_id);
94+
95+
autofill_view_info_h view_info = nullptr;
96+
autofill_view_info_create(&view_info);
97+
autofill_view_info_set_app_id(view_info, app_id);
98+
autofill_view_info_set_view_id(view_info, id.c_str());
99+
100+
for (auto hint : hints) {
101+
std::optional<autofill_hint_e> autofill_hint = ConvertAutofillHint(hint);
102+
if (autofill_hint.has_value()) {
103+
autofill_item_h item;
104+
autofill_item_create(&item);
105+
autofill_item_set_autofill_hint(item, autofill_hint.value());
106+
autofill_item_set_id(item, id.c_str());
107+
autofill_item_set_sensitive_data(item, false);
108+
autofill_view_info_add_item(view_info, item);
109+
autofill_item_destroy(item);
110+
}
111+
}
112+
113+
int ret = autofill_fill_request(ah_, view_info);
114+
if (ret != AUTOFILL_ERROR_NONE) {
115+
FT_LOG(Error) << "autofill_fill_request error";
116+
}
117+
autofill_view_info_destroy(view_info);
118+
119+
response_items_.clear();
120+
}
121+
122+
void TizenAutofill::RegisterAutofillItem(std::string view_id,
123+
AutofillItem item) {
124+
autofill_save_item_h si_h;
125+
126+
autofill_save_item_create(&si_h);
127+
autofill_save_item_set_autofill_hint(si_h, item.hint_);
128+
autofill_save_item_set_id(si_h, item.id_.c_str());
129+
autofill_save_item_set_label(si_h, item.label_.c_str());
130+
autofill_save_item_set_sensitive_data(si_h, item.sensitive_data_);
131+
autofill_save_item_set_value(si_h, item.value_.c_str());
132+
133+
char* app_id;
134+
app_get_id(&app_id);
135+
136+
autofill_save_view_info_h svi_h;
137+
138+
autofill_save_view_info_create(&svi_h);
139+
autofill_save_view_info_set_app_id(svi_h, app_id);
140+
autofill_save_view_info_set_view_id(svi_h, view_id.c_str());
141+
142+
autofill_save_view_info_add_item(svi_h, si_h);
143+
144+
if (app_id) {
145+
free(app_id);
146+
}
147+
148+
int ret;
149+
150+
ret = autofill_commit(ah_, svi_h);
151+
if (ret != AUTOFILL_ERROR_NONE) {
152+
FT_LOG(Error) << "autofill_commit error";
153+
}
154+
155+
autofill_save_view_info_destroy(svi_h);
156+
}
157+
158+
std::optional<autofill_hint_e> TizenAutofill::ConvertAutofillHint(
159+
std::string hint) {
160+
if (hint == "creditCardExpirationDate") {
161+
return AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE;
162+
} else if (hint == "creditCardExpirationDay") {
163+
return AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY;
164+
} else if (hint == "creditCardExpirationMonth") {
165+
return AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH;
166+
} else if (hint == "creditCardExpirationYear") {
167+
return AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR;
168+
} else if (hint == "email") {
169+
return AUTOFILL_HINT_EMAIL_ADDRESS;
170+
} else if (hint == "name") {
171+
return AUTOFILL_HINT_NAME;
172+
} else if (hint == "telephoneNumber") {
173+
return AUTOFILL_HINT_PHONE;
174+
} else if (hint == "postalAddress") {
175+
return AUTOFILL_HINT_POSTAL_ADDRESS;
176+
} else if (hint == "postalCode") {
177+
return AUTOFILL_HINT_POSTAL_CODE;
178+
} else if (hint == "username") {
179+
return AUTOFILL_HINT_ID;
180+
} else if (hint == "password") {
181+
return AUTOFILL_HINT_PASSWORD;
182+
} else if (hint == "creditCardSecurityCode") {
183+
return AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE;
184+
}
185+
FT_LOG(Error) << "Not supported autofill hint : " << hint;
186+
return std::nullopt;
187+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright 2023 Samsung Electronics Co., Ltd. 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+
#ifndef EMBEDDER_TIZEN_AUTOFILL_H_
6+
#define EMBEDDER_TIZEN_AUTOFILL_H_
7+
8+
#include <functional>
9+
#include <memory>
10+
#include <optional>
11+
#include <string>
12+
#include <vector>
13+
14+
#include <autofill.h>
15+
16+
struct AutofillItem {
17+
autofill_hint_e hint_;
18+
bool sensitive_data_;
19+
std::string label_;
20+
std::string id_;
21+
std::string value_;
22+
};
23+
24+
class TizenAutofill {
25+
public:
26+
static TizenAutofill& GetInstance() {
27+
static TizenAutofill instance = TizenAutofill();
28+
return instance;
29+
}
30+
31+
void RequestAutofill(std::vector<std::string> hints, std::string id);
32+
33+
void RegisterAutofillItem(std::string view_id, AutofillItem item);
34+
35+
void StoreResponseItem(std::unique_ptr<AutofillItem> item) {
36+
response_items_.push_back(move(item));
37+
}
38+
39+
void SetPopupCallback(std::function<void()> callback) {
40+
popup_callback_ = callback;
41+
}
42+
43+
void SetCommitCallback(std::function<void(std::string)> callback) {
44+
commit_callback_ = callback;
45+
}
46+
47+
void OnCommit(std::string str) { commit_callback_(str); }
48+
49+
void CallPopupCallback() {
50+
popup_callback_();
51+
// response_items_.clear();
52+
// TODO : reponse_item_ must be cleared when popup is disappeared
53+
}
54+
55+
const std::vector<std::unique_ptr<AutofillItem>>& GetAutofillItems() {
56+
return response_items_;
57+
}
58+
59+
private:
60+
TizenAutofill();
61+
62+
~TizenAutofill();
63+
64+
void InitailizeAutofill();
65+
66+
// TODO : implement convert flutter hint to tizen hint function
67+
std::optional<autofill_hint_e> ConvertAutofillHint(std::string hint);
68+
69+
autofill_h ah_;
70+
71+
std::vector<std::unique_ptr<AutofillItem>> response_items_;
72+
73+
std::function<void()> popup_callback_;
74+
75+
std::function<void(std::string)> commit_callback_;
76+
};
77+
78+
#endif

flutter/shell/platform/tizen/tizen_input_method_context.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ void TizenInputMethodContext::ShowInputPanel() {
259259
FT_ASSERT(imf_context_);
260260
ecore_imf_context_input_panel_show(imf_context_);
261261
ecore_imf_context_focus_in(imf_context_);
262+
int x = 0, y = 0, w = 0, h = 0;
263+
264+
ecore_imf_context_input_panel_geometry_get(imf_context_, &x, &y, &w, &h);
265+
FT_LOG(Error) << x << " " << y << " " << w << " " << h;
262266
}
263267

264268
void TizenInputMethodContext::HideInputPanel() {
@@ -275,7 +279,6 @@ bool TizenInputMethodContext::IsInputPanelShown() {
275279

276280
void TizenInputMethodContext::SetEnableSuggestions(bool enable) {
277281
FT_ASSERT(imf_context_);
278-
279282
ecore_imf_context_prediction_allow_set(imf_context_,
280283
enable ? EINA_TRUE : EINA_FALSE);
281284
}

0 commit comments

Comments
 (0)