1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "frameworks/bridge/common/dom/dom_video.h"
17 
18 #include "frameworks/bridge/common/utils/utils.h"
19 
20 namespace OHOS::Ace::Framework {
21 namespace {
22 
23 constexpr uint32_t METHOD_VIDEO_TO_ARGS_SIZE = 1;
24 
25 }
26 
DOMVideo(NodeId nodeId,const std::string & nodeName)27 DOMVideo::DOMVideo(NodeId nodeId, const std::string& nodeName) : DOMNode(nodeId, nodeName)
28 {
29     videoChild_ = AceType::MakeRefPtr<VideoComponent>();
30     videoChild_->SetFullscreenEvent([weak = AceType::WeakClaim(this)](bool fullscreen, const WeakPtr<Player>& player,
31                                         const WeakPtr<Texture>& texture) {
32         auto client = weak.Upgrade();
33         RefPtr<OHOS::Ace::Component> result;
34         if (client) {
35             result = client->FireFullscreen(fullscreen, player, texture);
36         }
37         return result;
38     });
39     if (IsRightToLeft()) {
40         videoChild_->SetTextDirection(TextDirection::RTL);
41     }
42 }
43 
SetSpecializedAttr(const std::pair<std::string,std::string> & attr)44 bool DOMVideo::SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
45 {
46     // Operator map for attr
47     static const std::unordered_map<std::string, void (*)(const RefPtr<VideoComponent>&, const std::string&)>
48         attrOperators = {
49             { DOM_VIDEO_MUTED,
50                 [](const RefPtr<VideoComponent>& video, const std::string& val) {
51                     video->SetMute(StringToBool(val));
52                 } },
53             { DOM_VIDEO_SRC,
54                 [](const RefPtr<VideoComponent>& video, const std::string& val) {
55                     video->SetSrc(val);
56                 } },
57             { DOM_VIDEO_AUTOPLAY,
58                 [](const RefPtr<VideoComponent>& video, const std::string& val) {
59                     video->SetAutoPlay(StringToBool(val));
60                 } },
61             { DOM_VIDEO_POSTER,
62                 [](const RefPtr<VideoComponent>& video, const std::string& val) {
63                     video->SetPoster(val);
64                 } },
65             { DOM_VIDEO_CONTROLS,
66                 [](const RefPtr<VideoComponent>& video, const std::string& val) {
67                     video->SetNeedControls(StringToBool(val));
68                 } },
69             { DOM_VIDEO_LOOP,
70                 [](const RefPtr<VideoComponent>& video, const std::string& val) {
71                     video->SetLoop(StringToBool(val));
72                 } },
73             { DOM_VIDEO_START_TIME,
74                 [](const RefPtr<VideoComponent>& video, const std::string& val) {
75                     video->SetStartTime(StringToInt(val));
76                 } },
77             { DOM_VIDEO_SPEED, [](const RefPtr<VideoComponent>& video, const std::string& val) {
78                     video->SetSpeed(StringUtils::StringToDouble(val));
79                 } },
80             { DOM_VIDEO_DIRECTION, [](const RefPtr<VideoComponent>& video, const std::string& val) {
81                     video->SetDirection(val);
82                 } },
83         };
84     auto operatorIter = attrOperators.find(attr.first);
85     if (operatorIter != attrOperators.end()) {
86         operatorIter->second(videoChild_, attr.second);
87         return true;
88     }
89     return false;
90 }
91 
SetSpecializedStyle(const std::pair<std::string,std::string> & style)92 bool DOMVideo::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
93 {
94     // Operator map for styles
95     static const std::unordered_map<std::string, void (*)(const RefPtr<VideoComponent>&, const std::string&)>
96         styleOperators = {
97             // Set video-fit
98             { DOM_VIDEO_FIT, [](const RefPtr<VideoComponent>& video,
99                              const std::string& val) { video->SetFit(ConvertStrToFit(val)); } },
100             // Set video-position
101             { DOM_VIDEO_POSITION, [](const RefPtr<VideoComponent>& video,
102                                 const std::string& val) { video->SetImagePosition(ConvertStrToPosition(val)); } },
103         };
104     auto operatorIter = styleOperators.find(style.first);
105     if (operatorIter != styleOperators.end()) {
106         operatorIter->second(videoChild_, style.second);
107         return true;
108     }
109     return false;
110 }
111 
AddSpecializedEvent(int32_t pageId,const std::string & event)112 bool DOMVideo::AddSpecializedEvent(int32_t pageId, const std::string& event)
113 {
114     // Operator map for event
115     static const std::unordered_map<std::string, void (*)(const RefPtr<VideoComponent>&, const EventMarker&)>
116         eventOperators = {
117             { DOM_VIDEO_EVENT_PREPARED, [](const RefPtr<VideoComponent>& video,
118                                         const EventMarker& event) { video->SetPreparedEventId(event); } },
119             { DOM_VIDEO_EVENT_START,
120                 [](const RefPtr<VideoComponent>& video, const EventMarker& event) { video->SetStartEventId(event); } },
121             { DOM_VIDEO_EVENT_PAUSE,
122                 [](const RefPtr<VideoComponent>& video, const EventMarker& event) { video->SetPauseEventId(event); } },
123             { DOM_VIDEO_EVENT_STOP,
124                 [](const RefPtr<VideoComponent>& video, const EventMarker& event) { video->SetStopEventId(event); } },
125             { DOM_VIDEO_EVENT_FINISH,
126                 [](const RefPtr<VideoComponent>& video, const EventMarker& event) { video->SetFinishEventId(event); } },
127             { DOM_VIDEO_EVENT_ERROR,
128                 [](const RefPtr<VideoComponent>& video, const EventMarker& event) { video->SetErrorEventId(event); } },
129             { DOM_VIDEO_EVENT_SEEKING, [](const RefPtr<VideoComponent>& video,
130                                        const EventMarker& event) { video->SetSeekingEventId(event); } },
131             { DOM_VIDEO_EVENT_SEEKED,
132                 [](const RefPtr<VideoComponent>& video, const EventMarker& event) { video->SetSeekedEventId(event); } },
133             { DOM_VIDEO_EVENT_TIMEUPDATE, [](const RefPtr<VideoComponent>& video,
134                                           const EventMarker& event) { video->SetTimeUpdateEventId(event); } },
135             { DOM_VIDEO_EVENT_FULLSCREENCHANGE,
136                 [](const RefPtr<VideoComponent>& video, const EventMarker& event) {
137                     video->SetFullscreenChangeEventId(event);
138                 } },
139         };
140     auto operatorIter = eventOperators.find(event);
141     if (operatorIter != eventOperators.end()) {
142         operatorIter->second(videoChild_, EventMarker(GetNodeIdForEvent(), event, pageId));
143         return true;
144     }
145     return false;
146 }
147 
CallSpecializedMethod(const std::string & method,const std::string & args)148 void DOMVideo::CallSpecializedMethod(const std::string& method, const std::string& args)
149 {
150     // Operator map for method
151     static const std::unordered_map<std::string, void (*)(const RefPtr<VideoComponent>&, const std::string&)>
152         methedOperators = {
153             { DOM_VIDEO_METHOD_START, [](const RefPtr<VideoComponent>& video, const std::string& args) {
154                     auto controller = video->GetVideoController();
155                     ACE_DCHECK(controller);
156                     controller->Start();
157                 } },
158             { DOM_VIDEO_METHOD_PAUSE, [](const RefPtr<VideoComponent>& video, const std::string& args) {
159                     auto controller = video->GetVideoController();
160                     ACE_DCHECK(controller);
161                     controller->Pause();
162                 } },
163             { DOM_VIDEO_METHOD_STOP, [](const RefPtr<VideoComponent>& video, const std::string& args) {
164                   auto controller = video->GetVideoController();
165                   ACE_DCHECK(controller);
166                   controller->Stop();
167                 } },
168             { DOM_VIDEO_METHOD_SEEK_TO, [](const RefPtr<VideoComponent>& video, const std::string& args) {
169                     auto controller = video->GetVideoController();
170                     ACE_DCHECK(controller);
171                     auto value = GetParamFromJson(args, "currenttime");
172                     if (value) {
173                         int32_t pos = value->GetInt();
174                         controller->SeekTo(pos);
175                     }
176                 } },
177             { DOM_VIDEO_METHOD_REQUEST_FULLSCREEN, [](const RefPtr<VideoComponent>& video, const std::string& args) {
178                     auto controller = video->GetVideoController();
179                     ACE_DCHECK(controller);
180                     auto value = GetParamFromJson(args, "screenOrientation ");
181                     if (value) {
182                         controller->RequestFullscreen(!(value->GetString() == "landscape"));
183                     }
184                 } },
185             { DOM_VIDEO_METHOD_EXIT_FULLSCREEN, [](const RefPtr<VideoComponent>& video, const std::string& args) {
186                     auto controller = video->GetVideoController();
187                     ACE_DCHECK(controller);
188                     controller->ExitFullscreen(false);
189                 } },
190         };
191     auto operatorIter = methedOperators.find(method);
192     if (operatorIter != methedOperators.end()) {
193         operatorIter->second(videoChild_, args);
194     }
195 }
196 
GetParamFromJson(const std::string & json,const std::string & key)197 std::unique_ptr<JsonValue> DOMVideo::GetParamFromJson(const std::string& json, const std::string& key)
198 {
199     std::unique_ptr<JsonValue> argsValue = JsonUtil::ParseJsonString(json);
200     if (!argsValue || !argsValue->IsArray() || argsValue->GetArraySize() != METHOD_VIDEO_TO_ARGS_SIZE) {
201         LOGW("Video parse args error");
202         return nullptr;
203     }
204 
205     std::unique_ptr<JsonValue> Value = argsValue->GetArrayItem(0)->GetValue(key);
206     if (!Value) {
207         return nullptr;
208     }
209     return Value;
210 }
211 
FireFullscreen(bool isFullScreen,const WeakPtr<Player> & player,const WeakPtr<Texture> & texture)212 RefPtr<Component> DOMVideo::FireFullscreen(
213     bool isFullScreen, const WeakPtr<Player>& player, const WeakPtr<Texture>& texture)
214 {
215     const auto& composed = GetRootComponent();
216     ACE_DCHECK(composed);
217     if (isFullScreen) {
218         if (isFullscreen_) {
219             return nullptr;
220         }
221         originComponent_ = composed->GetChild();
222         videoChild_->SetFullscreen(true);
223         videoChild_->SetPlayer(player);
224         videoChild_->SetTexture(texture);
225         composed->SetChild(GetEventComponents(videoChild_));
226         isFullscreen_ = true;
227     } else {
228         if (!isFullscreen_) {
229             return nullptr;
230         }
231         if (!originComponent_) {
232             return nullptr;
233         }
234         videoChild_->SetFullscreen(false);
235         videoChild_->SetPlayer(nullptr);
236         videoChild_->SetTexture(nullptr);
237         composed->SetChild(originComponent_);
238         isFullscreen_ = false;
239 
240         auto controller = videoChild_->GetVideoController();
241         ACE_DCHECK(controller);
242         controller->ExitFullscreen(true);
243         return nullptr;
244     }
245 
246     return GetRootComponent();
247 }
248 
GetEventComponents(const RefPtr<Component> & videoChild)249 RefPtr<Component> DOMVideo::GetEventComponents(const RefPtr<Component>& videoChild)
250 {
251     std::vector<RefPtr<SoleChildComponent>> components;
252     RefPtr<FocusableComponent> focusableEventComponent = GetFocusableComponent();
253     if (focusableEventComponent) {
254         components.emplace_back(focusableEventComponent);
255     }
256     RefPtr<TouchListenerComponent> touchEventComponent = GetTouchListenerComponent();
257     if (touchEventComponent) {
258         components.emplace_back(touchEventComponent);
259     }
260     RefPtr<GestureListenerComponent> gestureEventComponent = GetGestureListenerComponent();
261     if (gestureEventComponent) {
262         components.emplace_back(gestureEventComponent);
263     }
264     RefPtr<MouseListenerComponent> mouseEventComponent = GetMouseListenerComponent();
265     if (mouseEventComponent) {
266         components.emplace_back(mouseEventComponent);
267     }
268     for (int32_t idx = static_cast<int32_t>(components.size()) - 1; idx >= 1; --idx) {
269         components[idx - 1]->SetChild(components[idx]);
270     }
271 
272     auto box = AceType::MakeRefPtr<BoxComponent>();
273     Component::MergeRSNode(box);
274     RefPtr<BoxComponent> oldBox = GetBoxComponent();
275     if (oldBox) {
276         box->SetOnClick(oldBox->GetOnClick());
277     }
278     box->SetChild(videoChild);
279 
280     if (!components.empty()) {
281         const auto& lastEventComponent = components.back();
282         if (lastEventComponent) {
283             lastEventComponent->SetChild(box);
284             return components.front();
285         }
286     }
287     return box;
288 }
289 
ConvertStrToFit(const std::string & fit)290 ImageFit DOMVideo::ConvertStrToFit(const std::string& fit)
291 {
292     static const std::unordered_map<std::string, ImageFit> IMAGE_FIT_TABLE = {
293         { "fill", ImageFit::FILL },
294         { "contain", ImageFit::CONTAIN },
295         { "cover", ImageFit::COVER },
296         { "scaledown", ImageFit::SCALE_DOWN },
297         { "none", ImageFit::NONE },
298     };
299     auto imageFitIter = IMAGE_FIT_TABLE.find(fit);
300     return imageFitIter != IMAGE_FIT_TABLE.end() ? imageFitIter->second : ImageFit::CONTAIN;
301 }
302 
ConvertStrToPosition(const std::string & position)303 ImageObjectPosition DOMVideo::ConvertStrToPosition(const std::string& position)
304 {
305     ImageObjectPosition objectPosition;
306     ParseBackgroundImagePosition(position, objectPosition);
307     return objectPosition;
308 }
309 
310 } // namespace OHOS::Ace::Framework
311