| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| #include "third_party/json11/json11.hpp" |
| #include "core/bridge/eagle_bridge.h" |
| #include "base/string_util.h" |
| #include "base/closure.h" |
| #include "core/render/node/render_object.h" |
| #include "core/render/node/factory/render_creator.h" |
| #include "core/render/manager/render_manager.h" |
| #include "core/manager/weex_core_manager.h" |
| #include "core/network/http_module.h" |
| |
| namespace WeexCore { |
| |
| EagleBridge* EagleBridge::g_instance = nullptr;// NOLINT(cert-err58-cpp) |
| |
| void EagleBridge::CreatePage(const char* plugin_type, |
| const char* instanceId, |
| const char* func, |
| const char* script, |
| int script_length, |
| const char* opts, |
| const char* initData, |
| const char* extendsApi, std::function<void(const char*, const char*)> callback) { |
| const auto& it = pages_.find(instanceId); |
| if (it == pages_.end()){ |
| DataRenderHandler* plugin = get_data_render_handler(plugin_type); |
| if (!plugin) { |
| std::string err = std::string("EagleBridge plugin not exist: ") + plugin_type; |
| weex_core_handler()->ReportException(instanceId, "CreateInstance", err.c_str()); |
| LOGE("%s", err.c_str()); |
| return; |
| } |
| |
| pages_[instanceId] = plugin; |
| plugin->CreatePage(instanceId, func, script, script_length, opts, initData, extendsApi, callback); |
| } else { |
| LOGE("ReCreate Page of InstanceId: %s", instanceId); |
| } |
| } |
| |
| EagleBridge::EagleBridge() : weex_core_handler_(new WeexCoreHandler()) { |
| |
| } |
| |
| EagleBridge::DataRenderHandler* EagleBridge::data_render_handler(const std::string& instance_id) const { |
| const auto& it = pages_.find(instance_id); |
| if (it == pages_.end()){ |
| return nullptr; |
| } else { |
| return it->second; |
| } |
| } |
| |
| void EagleBridge::set_data_render_handler(const std::string& plugin_type, |
| DataRenderHandler* data_render_handler) { |
| std::lock_guard<std::mutex> lock(plugin_mutex_); |
| plugins_[plugin_type] = data_render_handler; |
| } |
| |
| EagleBridge::DataRenderHandler* EagleBridge::get_data_render_handler(const std::string& plugin_type) { |
| std::lock_guard<std::mutex> lock(plugin_mutex_); |
| const auto& it = plugins_.find(plugin_type); |
| if (it == plugins_.end()) { |
| return nullptr; |
| } else { |
| return it->second; |
| } |
| } |
| |
| EagleBridge* EagleBridge::GetInstance() { |
| static std::once_flag s_flag; |
| std::call_once(s_flag, []() { |
| g_instance = new EagleBridge(); |
| }); |
| |
| return g_instance; |
| } |
| |
| EagleModeReturn EagleBridge::DestroyPage(const char* instanceId) { |
| const auto& it = pages_.find(instanceId); |
| if (it == pages_.end()){ |
| return EagleModeReturn::NOT_EAGLE; |
| } else { |
| EagleModeReturn mode = it->second->DestroyInstance(instanceId); |
| pages_.erase(it); |
| return mode; |
| } |
| } |
| |
| EagleModeReturn EagleBridge::RefreshPage(const char* instanceId, const char* initData) { |
| const auto& it = pages_.find(instanceId); |
| if (it == pages_.end()){ |
| return EagleModeReturn::NOT_EAGLE; |
| } else { |
| return it->second->RefreshPage(instanceId, initData);; |
| } |
| } |
| |
| void EagleBridge::UpdateComponentData(const char* instanceId, const char* cid, const char* json_data) { |
| const auto& it = pages_.find(instanceId); |
| if (it == pages_.end()){ |
| weex_core_handler()->ReportException( |
| instanceId, "UpdateComponentData", |
| "There is no data_render_handler when UpdateComponentData invoked"); |
| return; |
| } else { |
| return it->second->UpdateComponentData(instanceId, cid, json_data);; |
| } |
| } |
| |
| bool EagleBridge::CallEagleTaskFromWeex(const char* instanceId, |
| const char* task, |
| const char* options) { |
| if (instanceId){ |
| //a single instance task |
| const auto& it = pages_.find(instanceId); |
| if (it == pages_.end()){ |
| return false; |
| } else { |
| return it->second->CallEagleTaskFromWeex(instanceId, task, options); |
| } |
| } else { |
| //a global task; call every plugins. |
| bool support = false; |
| for (const auto& it: plugins_){ |
| support = support || it.second->CallEagleTaskFromWeex(nullptr, task ,options); |
| } |
| return support; |
| } |
| return false; |
| } |
| |
| EagleRenderObject::EagleRenderObject() : render_object_impl_(nullptr) {} |
| |
| EagleRenderObject::EagleRenderObject(RenderObject* render_object) : render_object_impl_( |
| render_object) {} |
| |
| void EagleRenderObject::AddAttr(const std::string& key, const std::string& value) { |
| render_object_impl_->AddAttr(key, value); |
| } |
| |
| void EagleRenderObject::AddStyle(const std::string& key, const std::string& value) { |
| if (render_object_impl_->is_richtext_child()) { |
| render_object_impl_->MapInsertOrAssign(render_object_impl_->styles(), key, value); |
| } else { |
| render_object_impl_->AddStyle(key, value, false); |
| } |
| } |
| |
| void EagleRenderObject::UpdateAttr(const std::string& key, const std::string& value) { |
| render_object_impl_->UpdateAttr(key, value); |
| } |
| |
| void EagleRenderObject::UpdateStyle(const std::string& key, const std::string& value) { |
| render_object_impl_->UpdateStyle(key, value); |
| } |
| |
| void EagleRenderObject::AddEvent(const std::string& event) { |
| render_object_impl_->AddEvent(event); |
| } |
| |
| void EagleRenderObject::RemoveEvent(const std::string& event) { |
| render_object_impl_->RemoveEvent(event); |
| } |
| |
| std::set<std::string>* EagleRenderObject::events() { |
| return render_object_impl_->events(); |
| } |
| |
| void EagleRenderObject::set_page_id(const std::string& page_id) { |
| render_object_impl_->set_page_id(page_id); |
| } |
| |
| void EagleRenderObject::ApplyDefaultAttr() { |
| render_object_impl_->ApplyDefaultAttr(); |
| } |
| |
| void EagleRenderObject::ApplyDefaultStyle() { |
| render_object_impl_->ApplyDefaultStyle(false); |
| } |
| |
| int EagleRenderObject::AddRenderObject(int index, EagleRenderObject child) { |
| if (!render_object_impl_) { |
| return -1; |
| } |
| return render_object_impl_->AddRenderObject(index, child.render_object_impl_); |
| } |
| |
| int EagleRenderObject::getChildCount() { |
| return static_cast<int>(render_object_impl_->getChildCount()); |
| } |
| |
| int EagleRenderObject::getChildIndex(EagleRenderObject child) { |
| return static_cast<int>(render_object_impl_->IndexOf(child.render_object_impl_)); |
| } |
| |
| EagleRenderObject EagleRenderObject::GetChild(int index) { |
| return render_object_impl_->GetChild(index); |
| } |
| |
| void EagleRenderObject::set_is_richtext_child(const bool is_richtext_child) { |
| render_object_impl_->set_is_richtext_child(is_richtext_child); |
| } |
| |
| EagleRenderObject EagleRenderObject::parent_render() { |
| return render_object_impl_->parent_render(); |
| } |
| |
| const std::string& EagleRenderObject::page_id() { |
| return render_object_impl_->page_id(); |
| } |
| |
| const std::string& EagleRenderObject::ref() { |
| return render_object_impl_->ref(); |
| } |
| |
| void EagleRenderObject::RemoveRenderObject(EagleRenderObject child) { |
| render_object_impl_->RemoveRenderObject(child.render_object_impl_); |
| } |
| |
| EagleRenderObject EagleBridge::WeexCoreHandler::GetEagleRenderObject(const std::string& type, |
| const std::string& ref) { |
| return EagleRenderObject( |
| static_cast<WeexCore::RenderObject*>(WeexCore::RenderCreator::GetInstance()->CreateRender( |
| type, ref))); |
| } |
| |
| bool EagleBridge::WeexCoreHandler::CreatePage(const std::string& page_id, EagleRenderObject root) { |
| return RenderManager::GetInstance()->CreatePage(page_id, root.render_object_impl_); |
| } |
| |
| bool EagleBridge::WeexCoreHandler::HavePage(const std::string& page_id) { |
| return RenderManager::GetInstance()->GetPage(page_id) ? true : false; |
| } |
| |
| bool EagleBridge::WeexCoreHandler::CreateFinish(const std::string& page_id) { |
| return RenderManager::GetInstance()->CreateFinish(page_id); |
| } |
| |
| bool EagleBridge::WeexCoreHandler::ClosePage(const std::string& page_id) { |
| return RenderManager::GetInstance()->ClosePage(page_id); |
| } |
| |
| void EagleBridge::WeexCoreHandler::ReportException(const char* page_id, |
| const char* func, |
| const char* exception_string) { |
| WeexCore::WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->ReportException( |
| page_id, func, exception_string); |
| } |
| |
| void EagleBridge::WeexCoreHandler::Send(const char* instance_id, |
| const char* url, |
| std::function<void(const std::string&, |
| const std::string&)> callback) { |
| weex::core::network::HttpModule http_module; |
| http_module.Send(instance_id, url, callback); |
| } |
| |
| void EagleBridge::WeexCoreHandler::GetBundleType(const char* instance_id, |
| const char* content, |
| std::function<void(const std::string&, |
| const std::string&)> callback) { |
| weex::core::network::HttpModule http_module; |
| http_module.GetBundleType(instance_id, content, callback); |
| } |
| |
| //void EagleBridge::WeexCoreHandler::RequrieMoudle(const std::string& class_name) { |
| //} |
| |
| //void EagleBridge::WeexCoreHandler::RequrieComponent(const std::string& class_name) { |
| //} |
| |
| bool EagleBridge::WeexCoreHandler::RefreshFinish(const char* page_id, |
| const char* task, |
| const char* callback) { |
| WeexCore::WeexCoreManager::Instance() |
| ->getPlatformBridge() |
| ->core_side()->ForceLayout(page_id); |
| return static_cast<bool>(WeexCore::WeexCoreManager::Instance() |
| ->getPlatformBridge() |
| ->platform_side() |
| ->RefreshFinish(page_id, task, callback)); |
| } |
| |
| //return empty for undefined |
| static std::string ParsePlatformResultToString(const std::unique_ptr<ValueWithType>& result) { |
| switch (result->type) { |
| case ParamsType::DOUBLE: |
| return json11::Json(result->value.doubleValue).dump(); |
| case ParamsType::STRING: { |
| if (!result->value.string) { |
| return ""; |
| } else { |
| std::string ret; |
| if (result->value.string->length > 0) { |
| const auto& basic_string = weex::base::to_utf8(result->value.string->content, |
| result->value.string->length); |
| ret = json11::Json(basic_string).dump(); |
| } else { |
| ret = json11::Json("").dump(); |
| } |
| free(result->value.string); |
| return ret; |
| } |
| } |
| case ParamsType::BYTEARRAYSTRING: { |
| if (!result->value.byteArray) { |
| return "";//null |
| } else { |
| std::string ret; |
| if (result->value.byteArray->length > 0) { |
| ret = json11::Json(result->value.byteArray->content).dump(); |
| } else { |
| ret = json11::Json("").dump(); |
| } |
| free(result->value.byteArray); |
| return ret; |
| } |
| } |
| case ParamsType::JSONSTRING: { |
| if (!result->value.string) { |
| return ""; |
| } else { |
| std::string ret; |
| std::string err; |
| if (result->value.string->length > 0) { |
| const auto& raw_str = weex::base::to_utf8(result->value.string->content, |
| result->value.string->length); |
| |
| const json11::Json& json = json11::Json::parse(raw_str, err); |
| if (err.empty()) { |
| //succ |
| ret = json.dump(); |
| } else { |
| LOGE("VnodeManager CallNative return value to object err, %s", err.c_str()); |
| } |
| } |
| free(result->value.string); |
| return ret; |
| } |
| } |
| case ParamsType::BYTEARRAYJSONSTRING: { |
| if (!result->value.byteArray) { |
| return ""; |
| } else { |
| std::string ret; |
| std::string err; |
| if (result->value.string->length > 0) { |
| const json11::Json& json = json11::Json::parse(result->value.byteArray->content, err); |
| if (err.empty()) { |
| //succ |
| ret = json.dump(); |
| } else { |
| LOGE("VnodeManager CallNative return value to object err, %s", err.c_str()); |
| } |
| } |
| free(result->value.byteArray); |
| return ret; |
| } |
| } |
| case ParamsType::BYTEARRAY: |
| default: |
| return ""; |
| } |
| } |
| |
| std::string EagleBridge::WeexCoreHandler::CallNativeModule(const char* page_id, |
| const char* module, |
| const char* method, |
| const char* arguments, |
| int arguments_length, |
| const char* options, |
| int options_length) { |
| auto ptr = WeexCoreManager::Instance() |
| ->getPlatformBridge() |
| ->platform_side() |
| ->CallNativeModule(page_id, module, method, arguments, arguments_length, options, |
| options_length); |
| return ParsePlatformResultToString(ptr); |
| } |
| |
| #if OS_IOS |
| void EagleBridge::WeexCoreHandler::PostTaskOnComponentThread(const weex::base::Closure& closure) { |
| WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->PostTaskOnComponentThread(closure); |
| } |
| #endif |
| |
| void EagleBridge::WeexCoreHandler::CallNativeComponent(const char* page_id, |
| const char* module, |
| const char* method, |
| const char* arguments, |
| int arguments_length, |
| const char* options, |
| int options_length) { |
| WeexCoreManager::Instance() |
| ->getPlatformBridge() |
| ->platform_side() |
| ->CallNativeComponent(page_id, module, method, arguments, arguments_length, options, |
| options_length); |
| } |
| |
| void EagleBridge::WeexCoreHandler::NativeLog(const char* str_array) { |
| WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->NativeLog(str_array); |
| } |
| |
| bool EagleBridge::WeexCoreHandler::RemoveRenderObject(const std::string& page_id, |
| const std::string& ref) { |
| return RenderManager::GetInstance()->RemoveRenderObject(page_id, ref); |
| } |
| |
| bool EagleBridge::WeexCoreHandler::AddRenderObject(const std::string& page_id, |
| const std::string& parent_ref, |
| int index, |
| EagleRenderObject root) { |
| return RenderManager::GetInstance()->AddRenderObject(page_id, parent_ref, index, |
| root.render_object_impl_); |
| } |
| |
| bool EagleBridge::WeexCoreHandler::MoveRenderObject(const std::string& page_id, |
| const std::string& ref, |
| const std::string& parent_ref, |
| int index) { |
| return RenderManager::GetInstance()->MoveRenderObject(page_id, ref, parent_ref, index); |
| } |
| |
| bool EagleBridge::WeexCoreHandler::RemoveEvent(const std::string& page_id, const std::string& ref, |
| const std::string& event) { |
| return RenderManager::GetInstance()->RemoveEvent(page_id, ref, event); |
| } |
| |
| bool EagleBridge::WeexCoreHandler::AddEvent(const std::string& page_id, const std::string& ref, |
| const std::string& event) { |
| return RenderManager::GetInstance()->AddEvent(page_id, ref, event); |
| } |
| |
| bool EagleBridge::WeexCoreHandler::UpdateAttr(const std::string& page_id, const std::string& ref, |
| const char* data) { |
| return RenderManager::GetInstance()->UpdateAttr(page_id, ref, data); |
| } |
| |
| bool EagleBridge::WeexCoreHandler::UpdateAttr(const std::string& page_id, const std::string& ref, |
| std::vector<std::pair<std::string, std::string>>* attrPair) { |
| return RenderManager::GetInstance()->UpdateAttr(page_id, ref, attrPair); |
| } |
| |
| bool EagleBridge::WeexCoreHandler::UpdateStyle(const std::string& page_id, const std::string& ref, |
| const char* data) { |
| return RenderManager::GetInstance()->UpdateStyle(page_id, ref, data); |
| } |
| |
| bool EagleBridge::WeexCoreHandler::UpdateStyle(const std::string& page_id, const std::string& ref, |
| std::vector<std::pair<std::string, std::string>>* stylePair) { |
| return RenderManager::GetInstance()->UpdateStyle(page_id, ref, stylePair); |
| } |
| |
| int EagleBridge::WeexCoreHandler::ExecJS(const char* instanceId, const char* nameSpace, |
| const char* func, |
| std::vector<ValueWithType*>& params) { |
| return WeexCore::WeexCoreManager::Instance()->script_bridge()->script_side()->ExecJS( |
| instanceId, |
| nameSpace, |
| func, |
| params |
| ); |
| } |
| |
| //FIXME Please don't call this method, which will cause downgrade of Weex. |
| void EagleBridge::WeexCoreHandler::PostTaskToMsgLoop(const weex::base::Closure& closure) { |
| WeexCore::WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->ReportException( |
| "", "PostTaskToMsgLoop", |
| "PostTaskToMsgLoop is not supported anymore, please update to the latest version of Weex."); |
| } |
| |
| bool EagleBridge::WeexCoreHandler::CallWeexTaskFromEagle(const std::string& type, |
| const std::string& task, |
| const std::string& options) { |
| //No Extend Method now. |
| return false; |
| } |
| } |
| |