nacl_message_scanner.cc revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
10f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
20f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
30f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// found in the LICENSE file.
40f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
50f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "ppapi/proxy/nacl_message_scanner.h"
60f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
70f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include <vector>
80f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "base/bind.h"
90f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "ipc/ipc_message.h"
100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "ipc/ipc_message_macros.h"
110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h"
120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "ppapi/proxy/resource_message_params.h"
130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "ppapi/proxy/serialized_handle.h"
140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "ppapi/proxy/serialized_var.h"
150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)class NaClDescImcShm;
170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)namespace IPC {
190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)class Message;
200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)namespace {
230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)typedef std::vector<ppapi::proxy::SerializedHandle> Handles;
250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)struct ScanningResults {
270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  ScanningResults() : handle_index(0) {}
280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // Vector to hold handles found in the message.
300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  Handles handles;
310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // Current handle index in the rewritten message. During the scan, it will be
320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // be less than or equal to handles.size(). After the scan it should be equal.
330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  int handle_index;
340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // The rewritten message. This may be NULL, so all ScanParam overloads should
350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // check for NULL before writing to it. In some cases, a ScanParam overload
360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // may set this to NULL when it can determine that there are no parameters
370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // that need conversion. (See the ResourceMessageReplyParams overload.)
380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  scoped_ptr<IPC::Message> new_msg;
390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)};
400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void WriteHandle(int handle_index,
420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                 const ppapi::proxy::SerializedHandle& handle,
430f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                 IPC::Message* msg) {
440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  ppapi::proxy::SerializedHandle::WriteHeader(handle.header(), msg);
450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // Now write the handle itself in POSIX style.
470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  msg->WriteBool(true);  // valid == true
480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  msg->WriteInt(handle_index);
490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Define overloads for each kind of message parameter that requires special
520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// handling. See ScanTuple for how these get used.
530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Overload to match SerializedHandle.
550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void ScanParam(const ppapi::proxy::SerializedHandle& handle,
560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)               ScanningResults* results) {
570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  results->handles.push_back(handle);
580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (results->new_msg)
590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    WriteHandle(results->handle_index++, handle, results->new_msg.get());
600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void HandleWriter(int* handle_index,
630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                  IPC::Message* m,
640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                  const ppapi::proxy::SerializedHandle& handle) {
650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  WriteHandle((*handle_index)++, handle, m);
660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Overload to match SerializedVar, which can contain handles.
690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void ScanParam(const ppapi::proxy::SerializedVar& var,
700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)               ScanningResults* results) {
710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  std::vector<ppapi::proxy::SerializedHandle*> var_handles = var.GetHandles();
720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // Copy any handles and then rewrite the message.
730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  for (size_t i = 0; i < var_handles.size(); ++i)
740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    results->handles.push_back(*var_handles[i]);
750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (results->new_msg)
760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    var.WriteDataToMessage(results->new_msg.get(),
770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                           base::Bind(&HandleWriter, &results->handle_index));
780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// For PpapiMsg_ResourceReply and the reply to PpapiHostMsg_ResourceSyncCall,
810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// the handles are carried inside the ResourceMessageReplyParams.
820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// NOTE: We only intercept handles from host->NaCl. The only kind of
830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)//       ResourceMessageParams that travels this direction is
840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)//       ResourceMessageReplyParams, so that's the only one we need to handle.
850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void ScanParam(const ppapi::proxy::ResourceMessageReplyParams& params,
860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)               ScanningResults* results) {
870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // If the resource reply params don't contain handles, NULL the new message
880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // pointer to cancel further rewriting.
890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // NOTE: This works because only handles currently need rewriting, and we
900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  //       know at this point that this message has none.
910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (params.handles().empty()) {
920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    results->new_msg.reset(NULL);
930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    return;
940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // If we need to rewrite the message, write everything before the handles
970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // (there's nothing after the handles).
980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (results->new_msg) {
990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    params.WriteReplyHeader(results->new_msg.get());
1000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    // IPC writes the vector length as an int before the contents of the
1010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    // vector.
1020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    results->new_msg->WriteInt(static_cast<int>(params.handles().size()));
1030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
1040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  for (Handles::const_iterator iter = params.handles().begin();
1050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)       iter != params.handles().end();
1060f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)       ++iter) {
1070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    // ScanParam will write each handle to the new message, if necessary.
1080f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    ScanParam(*iter, results);
1090f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
1100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // Tell ResourceMessageReplyParams that we have taken the handles, so it
1110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // shouldn't close them. The NaCl runtime will take ownership of them.
1120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  params.ConsumeHandles();
1130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
1140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Overload to match all other types. If we need to rewrite the message,
1160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// write the parameter.
1170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)template <class T>
1180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void ScanParam(const T& param, ScanningResults* results) {
1190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (results->new_msg)
1200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    IPC::WriteParam(results->new_msg.get(), param);
1210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
1220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// These just break apart the given tuple and run ScanParam over each param.
1240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// The idea is to scan elements in the tuple which require special handling,
1250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// and write them into the |results| struct.
1260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)template <class A>
1270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void ScanTuple(const Tuple1<A>& t1, ScanningResults* results) {
1280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  ScanParam(t1.a, results);
1290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
1300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)template <class A, class B>
1310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void ScanTuple(const Tuple2<A, B>& t1, ScanningResults* results) {
1320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  ScanParam(t1.a, results);
1330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  ScanParam(t1.b, results);
1340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
1350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)template <class A, class B, class C>
1360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void ScanTuple(const Tuple3<A, B, C>& t1, ScanningResults* results) {
1370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  ScanParam(t1.a, results);
1380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  ScanParam(t1.b, results);
1390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  ScanParam(t1.c, results);
1400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
1410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)template <class A, class B, class C, class D>
1420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void ScanTuple(const Tuple4<A, B, C, D>& t1, ScanningResults* results) {
1430f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  ScanParam(t1.a, results);
1440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  ScanParam(t1.b, results);
1450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  ScanParam(t1.c, results);
1460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  ScanParam(t1.d, results);
1470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
1480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)template <class MessageType>
1500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)class MessageScannerImpl {
1510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) public:
1520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  explicit MessageScannerImpl(const IPC::Message* msg)
1530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      : msg_(static_cast<const MessageType*>(msg)) {
1540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
1550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  bool ScanMessage(ScanningResults* results) {
1560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    typename TupleTypes<typename MessageType::Schema::Param>::ValueTuple params;
1570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    if (!MessageType::Read(msg_, &params))
1580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      return false;
1590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    ScanTuple(params, results);
1600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    return true;
1610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
1620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  bool ScanReply(ScanningResults* results) {
1640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    typename TupleTypes<typename MessageType::Schema::ReplyParam>::ValueTuple
1650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        params;
1660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    if (!MessageType::ReadReplyParam(msg_, &params))
1670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      return false;
1680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    // If we need to rewrite the message, write the message id first.
1690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    if (results->new_msg) {
1700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      results->new_msg->set_reply();
1710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      int id = IPC::SyncMessage::GetMessageId(*msg_);
1720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      results->new_msg->WriteInt(id);
1730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    }
1740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    ScanTuple(params, results);
1750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    return true;
1760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
1770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // TODO(dmichael): Add ScanSyncMessage for outgoing sync messages, if we ever
1780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  //                 need to scan those.
1790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) private:
1810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  const MessageType* msg_;
1820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)};
1830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}  // namespace
1850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#define CASE_FOR_MESSAGE(MESSAGE_TYPE) \
1870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      case MESSAGE_TYPE::ID: { \
1880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        MessageScannerImpl<MESSAGE_TYPE> scanner(&msg); \
1890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        if (rewrite_msg) \
1900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)          results.new_msg.reset( \
1910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)              new IPC::Message(msg.routing_id(), msg.type(), \
1920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                               IPC::Message::PRIORITY_NORMAL)); \
1930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        if (!scanner.ScanMessage(&results)) \
1940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)          return false; \
1950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        break; \
1960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      }
1970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#define CASE_FOR_REPLY(MESSAGE_TYPE) \
1980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      case MESSAGE_TYPE::ID: { \
1990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        MessageScannerImpl<MESSAGE_TYPE> scanner(&msg); \
2000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        if (rewrite_msg) \
2010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)          results.new_msg.reset( \
2020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)              new IPC::Message(msg.routing_id(), msg.type(), \
2030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                               IPC::Message::PRIORITY_NORMAL)); \
2040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        if (!scanner.ScanReply(&results)) \
2050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)          return false; \
2060f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        break; \
2070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      }
2080f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2090f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)namespace ppapi {
2100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)namespace proxy {
2110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)class SerializedHandle;
2130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)NaClMessageScanner::NaClMessageScanner() {
2150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
2160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Windows IPC differs from POSIX in that native handles are serialized in the
2180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// message body, rather than passed in a separate FileDescriptorSet. Therefore,
2190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// on Windows, any message containing handles must be rewritten in the POSIX
2200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// format before we can send it to the NaCl plugin.
2210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)//
2220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// On POSIX and Windows we have to rewrite PpapiMsg_CreateNaClChannel messages.
2230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// These contain a handle with an invalid (place holder) descriptor. We need to
2240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// locate this handle so it can be replaced with a valid one when the channel is
2250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// created.
2260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)bool NaClMessageScanner::ScanMessage(
2270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    const IPC::Message& msg,
2280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    std::vector<SerializedHandle>* handles,
2290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    scoped_ptr<IPC::Message>* new_msg_ptr) {
2300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DCHECK(handles);
2310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DCHECK(handles->empty());
2320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DCHECK(new_msg_ptr);
2330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DCHECK(!new_msg_ptr->get());
2340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  bool rewrite_msg =
2360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#if defined(OS_WIN)
2370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      true;
2380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#else
2390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      (msg.type() == PpapiMsg_CreateNaClChannel::ID);
2400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#endif
2410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2430f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // We can't always tell from the message ID if rewriting is needed. Therefore,
2440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // scan any message types that might contain a handle. If we later determine
2450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // that there are no handles, we can cancel the rewriting by clearing the
2460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // results.new_msg pointer.
2470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  ScanningResults results;
2480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  switch (msg.type()) {
2490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    CASE_FOR_MESSAGE(PpapiMsg_CreateNaClChannel)
2500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    CASE_FOR_MESSAGE(PpapiMsg_PPBAudio_NotifyAudioStreamCreated)
2510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    CASE_FOR_MESSAGE(PpapiMsg_PPPMessaging_HandleMessage)
2520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    CASE_FOR_MESSAGE(PpapiPluginMsg_ResourceReply)
2530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case IPC_REPLY_ID: {
2540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      int id = IPC::SyncMessage::GetMessageId(msg);
2550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      PendingSyncMsgMap::iterator iter(pending_sync_msgs_.find(id));
2560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      if (iter == pending_sync_msgs_.end()) {
2570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        NOTREACHED();
2580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        return false;
2590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      }
2600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      uint32_t type = iter->second;
2610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      pending_sync_msgs_.erase(iter);
2620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      switch (type) {
2630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_GetTransferBuffer)
2640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        CASE_FOR_REPLY(PpapiHostMsg_PPBImageData_CreateSimple)
2650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        CASE_FOR_REPLY(PpapiHostMsg_ResourceSyncCall)
2660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        CASE_FOR_REPLY(PpapiHostMsg_SharedMemory_CreateSharedMemory)
2670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        default:
2680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)          // Do nothing for messages we don't know.
2690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)          break;
2700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      }
2710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      break;
2720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    }
2730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    default:
2740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      // Do nothing for messages we don't know.
2750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      break;
2760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
2770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // Only messages containing handles need to be rewritten. If no handles are
2790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // found, don't return the rewritten message either. This must be changed if
2800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // we ever add new param types that also require rewriting.
2810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (!results.handles.empty()) {
2820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    handles->swap(results.handles);
2830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    *new_msg_ptr = results.new_msg.Pass();
2840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
2850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  return true;
2860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
2870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void NaClMessageScanner::RegisterSyncMessageForReply(const IPC::Message& msg) {
2890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DCHECK(msg.is_sync());
2900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  int msg_id = IPC::SyncMessage::GetMessageId(msg);
2920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DCHECK(pending_sync_msgs_.find(msg_id) == pending_sync_msgs_.end());
2930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  pending_sync_msgs_[msg_id] = msg.type();
2950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
2960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}  // namespace proxy
2980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}  // namespace ppapi
299