| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef IPC_IPC_MESSAGE_UTILS_H_ |
| #define IPC_IPC_MESSAGE_UTILS_H_ |
| |
| #include<limits.h> |
| #include<stddef.h> |
| #include<stdint.h> |
| |
| #include<map> |
| #include<memory> |
| #include<optional> |
| #include<set> |
| #include<string> |
| #include<string_view> |
| #include<tuple> |
| #include<unordered_map> |
| #include<variant> |
| #include<vector> |
| |
| #include"base/check.h" |
| #include"base/compiler_specific.h" |
| #include"base/component_export.h" |
| #include"base/containers/flat_map.h" |
| #include"base/files/file.h" |
| #include"base/memory/platform_shared_memory_region.h" |
| #include"base/memory/read_only_shared_memory_region.h" |
| #include"base/memory/unsafe_shared_memory_region.h" |
| #include"base/memory/writable_shared_memory_region.h" |
| #include"base/numerics/safe_conversions.h" |
| #include"base/pickle.h" |
| #include"base/types/id_type.h" |
| #include"base/values.h" |
| #include"build/build_config.h" |
| #include"ipc/ipc_param_traits.h" |
| #include"third_party/abseil-cpp/absl/container/inlined_vector.h" |
| |
| #if BUILDFLAG(IS_ANDROID) |
| #include"base/android/scoped_hardware_buffer_handle.h" |
| #endif |
| |
| #if BUILDFLAG(IS_FUCHSIA) |
| #include<lib/zx/channel.h> |
| #include<lib/zx/vmo.h> |
| #endif |
| |
| #if BUILDFLAG(IS_WIN) |
| #include"base/strings/string_util_win.h" |
| #endif |
| |
| namespacebase{ |
| classFilePath; |
| classTime; |
| classTimeDelta; |
| classTimeTicks; |
| classUnguessableToken; |
| structFileDescriptor; |
| }// namespace base |
| |
| namespace IPC{ |
| |
| classMessage; |
| structChannelHandle; |
| |
| #if BUILDFLAG(IS_WIN) |
| classPlatformFileForTransit; |
| #endif |
| |
| // ----------------------------------------------------------------------------- |
| // How we send IPC message logs across channels. |
| struct COMPONENT_EXPORT(IPC)LogData{ |
| LogData(); |
| LogData(constLogData& other); |
| ~LogData(); |
| |
| std::string channel; |
| int32_t routing_id; |
| uint32_t type;// "User-defined" message type, from ipc_message.h. |
| std::string flags; |
| int64_t sent;// Time that the message was sent (i.e. at Send()). |
| int64_t receive;// Time before it was dispatched (i.e. before calling |
| // OnMessageReceived). |
| int64_t dispatch;// Time after it was dispatched (i.e. after calling |
| // OnMessageReceived). |
| std::string message_name; |
| std::stringparams; |
| }; |
| |
| //----------------------------------------------------------------------------- |
| |
| // A dummy struct to place first just to allow leading commas for all |
| // members in the macro-generated constructor initializer lists. |
| structNoParams{ |
| }; |
| |
| // Specializations are checked by 'IPC checker' part of find-bad-constructs |
| // Clang plugin (see WriteParam() below for the details). |
| template<typename...Ts> |
| structCheckedTuple{ |
| typedef std::tuple<Ts...>Tuple; |
| }; |
| |
| // This function is checked by 'IPC checker' part of find-bad-constructs |
| // Clang plugin to make it's not called on the following types: |
| // 1. long / unsigned long (but not typedefs to) |
| // 2. intmax_t, uintmax_t, intptr_t, uintptr_t, wint_t, |
| // size_t, rsize_t, ssize_t, ptrdiff_t, dev_t, off_t, clock_t, |
| // time_t, suseconds_t (including typedefs to) |
| // 3. Any template referencing types above (e.g. std::vector<size_t>) |
| template<class P> |
| inlinevoidWriteParam(base::Pickle* m,const P& p){ |
| typedeftypenameSimilarTypeTraits<P>::TypeType; |
| ParamTraits<Type>::Write(m,static_cast<constType&>(p)); |
| } |
| |
| template<class P> |
| [[nodiscard]]inlineboolReadParam(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| P* p){ |
| typedeftypenameSimilarTypeTraits<P>::TypeType; |
| returnParamTraits<Type>::Read(m, iter,reinterpret_cast<Type*>(p)); |
| } |
| |
| template<class P> |
| inlinevoidLogParam(const P& p, std::string* l){ |
| typedeftypenameSimilarTypeTraits<P>::TypeType; |
| ParamTraits<Type>::Log(static_cast<constType&>(p), l); |
| } |
| |
| // Primitive ParamTraits ------------------------------------------------------- |
| |
| template<> |
| structParamTraits<bool>{ |
| typedefbool param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ m->WriteBool(p);} |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| return iter->ReadBool(r); |
| } |
| COMPONENT_EXPORT(IPC)staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<signedchar>{ |
| typedefsignedchar param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<unsignedchar>{ |
| typedefunsignedchar param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<unsignedshort>{ |
| typedefunsignedshort param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| structParamTraits<int>{ |
| typedefint param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ m->WriteInt(p);} |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| return iter->ReadInt(r); |
| } |
| COMPONENT_EXPORT(IPC)staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| structParamTraits<unsignedint>{ |
| typedefunsignedint param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ |
| m->WriteInt(static_cast<int>(p)); |
| } |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| return iter->ReadInt(reinterpret_cast<int*>(r)); |
| } |
| COMPONENT_EXPORT(IPC)staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| // long isn't safe to send over IPC because it's 4 bytes on 32 bit builds but |
| // 8 bytes on 64 bit builds. So if a 32 bit and 64 bit process have a channel |
| // that would cause problem. |
| // We need to keep this on for a few configs: |
| // 1) Windows because DWORD is typedef'd to it, which is fine because we have |
| // very few IPCs that cross this boundary. |
| // 2) We also need to keep it for Linux for two reasons: int64_t is typedef'd |
| // to long, and gfx::PluginWindow is long and is used in one GPU IPC. |
| // 3) Android 64 bit and Fuchsia also have int64_t typedef'd to long. |
| // Since we want to support Android 32<>64 bit IPC, as long as we don't have |
| // these traits for 32 bit ARM then that'll catch any errors. |
| #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \ |
| BUILDFLAG(IS_FUCHSIA)|| \ |
| (BUILDFLAG(IS_ANDROID)&&defined(ARCH_CPU_64_BITS)) |
| template<> |
| structParamTraits<long>{ |
| typedeflong param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ |
| m->WriteLong(p); |
| } |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| return iter->ReadLong(r); |
| } |
| COMPONENT_EXPORT(IPC)staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| structParamTraits<unsignedlong>{ |
| typedefunsignedlong param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ |
| m->WriteLong(p); |
| } |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| return iter->ReadLong(reinterpret_cast<long*>(r)); |
| } |
| COMPONENT_EXPORT(IPC)staticvoidLog(const param_type& p, std::string* l); |
| }; |
| #endif |
| |
| template<> |
| structParamTraits<longlong>{ |
| typedeflonglong param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ |
| m->WriteInt64(static_cast<int64_t>(p)); |
| } |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| return iter->ReadInt64(reinterpret_cast<int64_t*>(r)); |
| } |
| COMPONENT_EXPORT(IPC)staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| structParamTraits<unsignedlonglong>{ |
| typedefunsignedlonglong param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ |
| m->WriteInt64(static_cast<int64_t>(p)); |
| } |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| return iter->ReadInt64(reinterpret_cast<int64_t*>(r)); |
| } |
| COMPONENT_EXPORT(IPC)staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients |
| // should be sure to check the sanity of these values after receiving them over |
| // IPC. |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<float>{ |
| typedeffloat param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ m->WriteFloat(p);} |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| return iter->ReadFloat(r); |
| } |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<double>{ |
| typedefdouble param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<class P,size_tSize> |
| structParamTraits<P[Size]>{ |
| using param_type= P[Size]; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ |
| for(const P& element: p) |
| WriteParam(m, element); |
| } |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| for(P& element:*r){ |
| if(!ReadParam(m, iter,&element)) |
| returnfalse; |
| } |
| returntrue; |
| } |
| staticvoidLog(const param_type& p, std::string* l){ |
| l->append("["); |
| for(const P& element: p){ |
| if(&element!=&p[0]) |
| l->append(" "); |
| LogParam(element, l); |
| } |
| l->append("]"); |
| } |
| }; |
| |
| // STL ParamTraits ------------------------------------------------------------- |
| |
| template<> |
| structParamTraits<std::string>{ |
| typedef std::string param_type; |
| staticvoidWrite(base::Pickle* m, std::string_view p){ m->WriteString(p);} |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| return iter->ReadString(r); |
| } |
| COMPONENT_EXPORT(IPC)staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| // Allow calling `WriteParam()` directly with a `std::string_view` argument |
| // instead of forcing callers to explicitly construct a `std::string` just to |
| // have the `Write()` specialization above turn it back into a |
| // `std::string_view`. |
| inlinevoidWriteParam(base::Pickle* m, std::string_view sv){ |
| ParamTraits<std::string>::Write(m, sv); |
| } |
| |
| template<> |
| structParamTraits<std::u16string>{ |
| typedef std::u16string param_type; |
| staticvoidWrite(base::Pickle* m, std::u16string_view p){ |
| m->WriteString16(p); |
| } |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| return iter->ReadString16(r); |
| } |
| COMPONENT_EXPORT(IPC)staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| // Allow calling `WriteParam()` directly with a `std::u16string_view` argument |
| // instead of forcing callers to explicitly construct a `std::u16string` just to |
| // have the `Write()` specialization above turn it back into a |
| // `std::u16string_view`. |
| inlinevoidWriteParam(base::Pickle* m, std::u16string_view sv){ |
| ParamTraits<std::u16string>::Write(m, sv); |
| } |
| |
| #if BUILDFLAG(IS_WIN) |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<std::wstring>{ |
| typedef std::wstring param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ |
| m->WriteString16(base::AsStringPiece16(p)); |
| } |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| #endif |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<std::vector<char>>{ |
| typedef std::vector<char> param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle*, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<std::vector<unsignedchar>>{ |
| typedef std::vector<unsignedchar> param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<std::vector<bool>>{ |
| typedef std::vector<bool> param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<class P> |
| structParamTraits<std::vector<P>>{ |
| typedef std::vector<P> param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ |
| WriteParam(m,base::checked_cast<int>(p.size())); |
| for(size_t i=0; i< p.size(); i++) |
| WriteParam(m, p[i]); |
| } |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| size_t size; |
| // ReadLength() checks for < 0 itself. |
| if(!iter->ReadLength(&size)) |
| returnfalse; |
| // Resizing beforehand is not safe, see BUG 1006367 for details. |
| if(size> INT_MAX/sizeof(P)) |
| returnfalse; |
| r->resize(size); |
| for(size_t i=0; i< size; i++){ |
| if(!ReadParam(m, iter,&(*r)[i])) |
| returnfalse; |
| } |
| returntrue; |
| } |
| staticvoidLog(const param_type& p, std::string* l){ |
| for(size_t i=0; i< p.size();++i){ |
| if(i!=0) |
| l->append(" "); |
| LogParam((p[i]), l); |
| } |
| } |
| }; |
| |
| template<class P> |
| structParamTraits<std::set<P>>{ |
| typedef std::set<P> param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ |
| WriteParam(m,base::checked_cast<int>(p.size())); |
| typename param_type::const_iterator iter; |
| for(iter= p.begin(); iter!= p.end();++iter) |
| WriteParam(m,*iter); |
| } |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| size_t size; |
| if(!iter->ReadLength(&size)) |
| returnfalse; |
| for(size_t i=0; i< size;++i){ |
| P item; |
| if(!ReadParam(m, iter,&item)) |
| returnfalse; |
| r->insert(item); |
| } |
| returntrue; |
| } |
| staticvoidLog(const param_type& p, std::string* l){ |
| l->append("<std::set>"); |
| } |
| }; |
| |
| template<class K,class V,class C,class A> |
| structParamTraits<std::map<K, V, C, A>>{ |
| typedef std::map<K, V, C, A> param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ |
| WriteParam(m,base::checked_cast<int>(p.size())); |
| for(constauto& iter: p){ |
| WriteParam(m, iter.first); |
| WriteParam(m, iter.second); |
| } |
| } |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| int size; |
| if(!ReadParam(m, iter,&size)|| size<0) |
| returnfalse; |
| for(int i=0; i< size;++i){ |
| K k; |
| if(!ReadParam(m, iter,&k)) |
| returnfalse; |
| V& value=(*r)[k]; |
| if(!ReadParam(m, iter,&value)) |
| returnfalse; |
| } |
| returntrue; |
| } |
| staticvoidLog(const param_type& p, std::string* l){ |
| l->append("<std::map>"); |
| } |
| }; |
| |
| template<class K,class V,class C,class A> |
| structParamTraits<std::unordered_map<K, V, C, A>>{ |
| typedef std::unordered_map<K, V, C, A> param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ |
| WriteParam(m,base::checked_cast<int>(p.size())); |
| for(constauto& iter: p){ |
| WriteParam(m, iter.first); |
| WriteParam(m, iter.second); |
| } |
| } |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| int size; |
| if(!ReadParam(m, iter,&size)|| size<0) |
| returnfalse; |
| for(int i=0; i< size;++i){ |
| K k; |
| if(!ReadParam(m, iter,&k)) |
| returnfalse; |
| V& value=(*r)[k]; |
| if(!ReadParam(m, iter,&value)) |
| returnfalse; |
| } |
| returntrue; |
| } |
| staticvoidLog(const param_type& p, std::string* l){ |
| l->append("<std::unordered_map>"); |
| } |
| }; |
| |
| template<class A,class B> |
| structParamTraits<std::pair<A, B>>{ |
| typedef std::pair<A, B> param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ |
| WriteParam(m, p.first); |
| WriteParam(m, p.second); |
| } |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| returnReadParam(m, iter,&r->first)&&ReadParam(m, iter,&r->second); |
| } |
| staticvoidLog(const param_type& p, std::string* l){ |
| l->append("("); |
| LogParam(p.first, l); |
| l->append(", "); |
| LogParam(p.second, l); |
| l->append(")"); |
| } |
| }; |
| |
| // Base ParamTraits ------------------------------------------------------------ |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<base::Value::Dict>{ |
| typedefbase::Value::Dict param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
| // FileDescriptors may be serialised over IPC channels on POSIX. On the |
| // receiving side, the FileDescriptor is a valid duplicate of the file |
| // descriptor which was transmitted: *it is not just a copy of the integer like |
| // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In |
| // this case, the receiving end will see a value of -1. *Zero is a valid file |
| // descriptor*. |
| // |
| // The received file descriptor will have the |auto_close| flag set to true. The |
| // code which handles the message is responsible for taking ownership of it. |
| // File descriptors are OS resources and must be closed when no longer needed. |
| // |
| // When sending a file descriptor, the file descriptor must be valid at the time |
| // of transmission. Since transmission is not synchronous, one should consider |
| // dup()ing any file descriptors to be transmitted and setting the |auto_close| |
| // flag, which causes the file descriptor to be closed after writing. |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<base::FileDescriptor>{ |
| typedefbase::FileDescriptor param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<base::ScopedFD>{ |
| typedefbase::ScopedFD param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| #endif// BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
| |
| #if BUILDFLAG(IS_WIN) |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<base::win::ScopedHandle>{ |
| using param_type=base::win::ScopedHandle; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| #endif |
| |
| #if BUILDFLAG(IS_FUCHSIA) |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<zx::vmo>{ |
| typedef zx::vmo param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<zx::channel>{ |
| typedef zx::channel param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| #endif// BUILDFLAG(IS_FUCHSIA) |
| |
| #if BUILDFLAG(IS_ANDROID) |
| template<> |
| struct COMPONENT_EXPORT(IPC) |
| ParamTraits<base::android::ScopedHardwareBufferHandle>{ |
| typedefbase::android::ScopedHardwareBufferHandle param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| #endif |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<base::ReadOnlySharedMemoryRegion>{ |
| typedefbase::ReadOnlySharedMemoryRegion param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<base::WritableSharedMemoryRegion>{ |
| typedefbase::WritableSharedMemoryRegion param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<base::UnsafeSharedMemoryRegion>{ |
| typedefbase::UnsafeSharedMemoryRegion param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC) |
| ParamTraits<base::subtle::PlatformSharedMemoryRegion>{ |
| typedefbase::subtle::PlatformSharedMemoryRegion param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC) |
| ParamTraits<base::subtle::PlatformSharedMemoryRegion::Mode>{ |
| typedefbase::subtle::PlatformSharedMemoryRegion::Mode param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| #if BUILDFLAG(IS_WIN) |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<PlatformFileForTransit>{ |
| typedefPlatformFileForTransit param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| #endif// BUILDFLAG(IS_WIN) |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<base::FilePath>{ |
| typedefbase::FilePath param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<base::Value::List>{ |
| typedefbase::Value::List param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<base::Value>{ |
| typedefbase::Value param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<base::File::Info>{ |
| typedefbase::File::Info param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| structSimilarTypeTraits<base::File::Error>{ |
| typedefintType; |
| }; |
| |
| #if BUILDFLAG(IS_WIN) |
| template<> |
| structSimilarTypeTraits<HWND>{ |
| typedef HANDLEType; |
| }; |
| #endif// BUILDFLAG(IS_WIN) |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<base::Time>{ |
| typedefbase::Time param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<base::TimeDelta>{ |
| typedefbase::TimeDelta param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<base::TimeTicks>{ |
| typedefbase::TimeTicks param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<base::UnguessableToken>{ |
| typedefbase::UnguessableToken param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| structParamTraits<std::tuple<>>{ |
| typedef std::tuple<> param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p){} |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| returntrue; |
| } |
| staticvoidLog(const param_type& p, std::string* l){ |
| } |
| }; |
| |
| template<typename T,int index,int count> |
| structTupleParamTraitsHelper{ |
| usingNext=TupleParamTraitsHelper<T, index+1, count>; |
| |
| staticvoidWrite(base::Pickle* m,const T& p){ |
| WriteParam(m, std::get<index>(p)); |
| Next::Write(m, p); |
| } |
| |
| staticboolRead(constbase::Pickle* m,base::PickleIterator* iter, T* r){ |
| returnReadParam(m, iter,&std::get<index>(*r))&&Next::Read(m, iter, r); |
| } |
| |
| staticvoidLog(const T& p, std::string* l){ |
| LogParam(std::get<index>(p), l); |
| if(index< count-1) |
| l->append(", "); |
| Next::Log(p, l); |
| } |
| }; |
| |
| template<typename T,int index> |
| structTupleParamTraitsHelper<T, index, index>{ |
| staticvoidWrite(base::Pickle* m,const T& p){} |
| staticboolRead(constbase::Pickle* m,base::PickleIterator* iter, T* r){ |
| returntrue; |
| } |
| staticvoidLog(const T& p, std::string* l){} |
| }; |
| |
| template<typename...Args> |
| structParamTraits<std::tuple<Args...>>{ |
| using param_type= std::tuple<Args...>; |
| usingHelper= |
| TupleParamTraitsHelper<param_type,0, std::tuple_size<param_type>::value>; |
| |
| staticvoidWrite(base::Pickle* m,const param_type& p){ |
| Helper::Write(m, p); |
| } |
| |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| returnHelper::Read(m, iter, r); |
| } |
| |
| staticvoidLog(const param_type& p, std::string* l){Helper::Log(p, l);} |
| }; |
| |
| template<class P,size_t stack_capacity> |
| structParamTraits<absl::InlinedVector<P, stack_capacity>>{ |
| typedef absl::InlinedVector<P, stack_capacity> param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ |
| WriteParam(m,base::checked_cast<int>(p.size())); |
| for(size_t i=0; i< p.size(); i++){ |
| WriteParam(m, p[i]); |
| } |
| } |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| size_t size; |
| if(!iter->ReadLength(&size)){ |
| returnfalse; |
| } |
| // Sanity check for the vector size. |
| if(size> INT_MAX/sizeof(P)){ |
| returnfalse; |
| } |
| P value; |
| for(size_t i=0; i< size; i++){ |
| if(!ReadParam(m, iter,&value)){ |
| returnfalse; |
| } |
| r->push_back(value); |
| } |
| returntrue; |
| } |
| staticvoidLog(const param_type& p, std::string* l){ |
| for(size_t i=0; i< p.size();++i){ |
| if(i!=0){ |
| l->append(" "); |
| } |
| LogParam((p[i]), l); |
| } |
| } |
| }; |
| |
| template<classKey,classMapped,classCompare> |
| structParamTraits<base::flat_map<Key,Mapped,Compare>>{ |
| using param_type=base::flat_map<Key,Mapped,Compare>; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ |
| DCHECK(base::IsValueInRangeForNumericType<int>(p.size())); |
| WriteParam(m,base::checked_cast<int>(p.size())); |
| for(constauto& iter: p){ |
| WriteParam(m, iter.first); |
| WriteParam(m, iter.second); |
| } |
| } |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| size_t size; |
| if(!iter->ReadLength(&size)) |
| returnfalse; |
| |
| // Construct by creating in a vector and moving into the flat_map. Properly |
| // serialized flat_maps will be in-order so this will be O(n). Incorrectly |
| // serialized ones will still be handled properly. |
| std::vector<typename param_type::value_type> vect; |
| vect.resize(size); |
| for(size_t i=0; i< size;++i){ |
| if(!ReadParam(m, iter,&vect[i].first)) |
| returnfalse; |
| if(!ReadParam(m, iter,&vect[i].second)) |
| returnfalse; |
| } |
| |
| *r= param_type(std::move(vect)); |
| returntrue; |
| } |
| staticvoidLog(const param_type& p, std::string* l){ |
| l->append("<base::flat_map>"); |
| } |
| }; |
| |
| template<class P> |
| structParamTraits<std::unique_ptr<P>>{ |
| typedef std::unique_ptr<P> param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ |
| bool valid=!!p; |
| WriteParam(m, valid); |
| if(valid) |
| WriteParam(m,*p); |
| } |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| bool valid=false; |
| if(!ReadParam(m, iter,&valid)) |
| returnfalse; |
| |
| if(!valid){ |
| r->reset(); |
| returntrue; |
| } |
| |
| param_type temp(new P()); |
| if(!ReadParam(m, iter, temp.get())) |
| returnfalse; |
| |
| r->swap(temp); |
| returntrue; |
| } |
| staticvoidLog(const param_type& p, std::string* l){ |
| if(p) |
| LogParam(*p, l); |
| else |
| l->append("NULL"); |
| } |
| }; |
| |
| // absl types ParamTraits |
| |
| template<class P> |
| structParamTraits<std::optional<P>>{ |
| typedef std::optional<P> param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ |
| constbool is_set=static_cast<bool>(p); |
| WriteParam(m, is_set); |
| if(is_set) |
| WriteParam(m, p.value()); |
| } |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| bool is_set=false; |
| if(!iter->ReadBool(&is_set)) |
| returnfalse; |
| if(is_set){ |
| P value; |
| if(!ReadParam(m, iter,&value)) |
| returnfalse; |
| *r= std::move(value); |
| } |
| returntrue; |
| } |
| staticvoidLog(const param_type& p, std::string* l){ |
| if(p) |
| LogParam(p.value(), l); |
| else |
| l->append("(unset)"); |
| } |
| }; |
| |
| template<> |
| structParamTraits<std::monostate>{ |
| typedef std::monostate param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p){} |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| returntrue; |
| } |
| staticvoidLog(const param_type& p, std::string* l){ l->append("()");} |
| }; |
| |
| // base/util types ParamTraits |
| |
| template<typenameTypeMarker,typenameWrappedType,WrappedType kInvalidValue> |
| structParamTraits<base::IdType<TypeMarker,WrappedType, kInvalidValue>>{ |
| using param_type=base::IdType<TypeMarker,WrappedType, kInvalidValue>; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ |
| WriteParam(m, p.GetUnsafeValue()); |
| } |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| WrappedType value; |
| if(!ReadParam(m, iter,&value)) |
| returnfalse; |
| *r= param_type::FromUnsafeValue(value); |
| returntrue; |
| } |
| staticvoidLog(const param_type& p, std::string* l){ |
| LogParam(p.GetUnsafeValue(), l); |
| } |
| }; |
| |
| template<typenameTagType,typenameUnderlyingType> |
| structParamTraits<base::StrongAlias<TagType,UnderlyingType>>{ |
| using param_type=base::StrongAlias<TagType,UnderlyingType>; |
| staticvoidWrite(base::Pickle* m,const param_type& p){ |
| WriteParam(m, p.value()); |
| } |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r){ |
| UnderlyingType value; |
| if(!ReadParam(m, iter,&value)) |
| returnfalse; |
| *r= param_type(value); |
| returntrue; |
| } |
| staticvoidLog(const param_type& p, std::string* l){ |
| LogParam(p.value(), l); |
| } |
| }; |
| |
| // IPC types ParamTraits ------------------------------------------------------- |
| |
| // A ChannelHandle is basically a platform-inspecific wrapper around the |
| // fact that IPC endpoints are handled specially on POSIX. See above comments |
| // on FileDescriptor for more background. |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<IPC::ChannelHandle>{ |
| typedefChannelHandle param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<LogData>{ |
| typedefLogData param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<Message>{ |
| staticvoidWrite(base::Pickle* m,constMessage& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| Message* r); |
| staticvoidLog(constMessage& p, std::string* l); |
| }; |
| |
| // Windows ParamTraits --------------------------------------------------------- |
| |
| #if BUILDFLAG(IS_WIN) |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<HANDLE>{ |
| typedef HANDLE param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| |
| template<> |
| struct COMPONENT_EXPORT(IPC)ParamTraits<MSG>{ |
| typedef MSG param_type; |
| staticvoidWrite(base::Pickle* m,const param_type& p); |
| staticboolRead(constbase::Pickle* m, |
| base::PickleIterator* iter, |
| param_type* r); |
| staticvoidLog(const param_type& p, std::string* l); |
| }; |
| #endif// BUILDFLAG(IS_WIN) |
| |
| //----------------------------------------------------------------------------- |
| // Generic message subclasses |
| |
| inlinevoidAddOutputParamsToLog(constMessage* msg, std::string* l){} |
| |
| template<classReplyParamType> |
| inlinevoidLogReplyParamsToMessage(constReplyParamType& reply_params, |
| constMessage* msg){} |
| |
| inlinevoidConnectMessageAndReply(constMessage* msg,Message* reply){} |
| |
| }// namespace IPC |
| |
| #endif// IPC_IPC_MESSAGE_UTILS_H_ |