Merge "add console log callbacks to the NaCl plugin for debugging"
diff --git a/unpacker/cpp/javascript_message_sender_interface.h b/unpacker/cpp/javascript_message_sender_interface.h
index 3f2b622..282356b 100644
--- a/unpacker/cpp/javascript_message_sender_interface.h
+++ b/unpacker/cpp/javascript_message_sender_interface.h
@@ -39,6 +39,16 @@
                                 const std::string& request_id,
                                 const pp::VarArrayBuffer& array_buffer,
                                 bool has_more_data) = 0;
+
+  virtual void SendConsoleLog(const std::string& file_system_id,
+                              const std::string& request_id,
+                              const std::string& src_file,
+                              int src_line,
+                              const std::string& src_func,
+                              const std::string& message) = 0;
 };
 
+#define CONSOLE_LOG(fsid, rid, msg) \
+  SendConsoleLog(fsid, rid, __FILE__, __LINE__, __func__, msg)
+
 #endif  // JAVASCRIPT_MESSAGE_SENDER_INTERFACE_H_
diff --git a/unpacker/cpp/module.cc b/unpacker/cpp/module.cc
index c8ae94b..c5fae8c 100644
--- a/unpacker/cpp/module.cc
+++ b/unpacker/cpp/module.cc
@@ -81,6 +81,16 @@
         file_system_id, request_id, array_buffer, has_more_data));
   }
 
+  virtual void SendConsoleLog(const std::string& file_system_id,
+                              const std::string& request_id,
+                              const std::string& src_file,
+                              int src_line,
+                              const std::string& src_func,
+                              const std::string& message) {
+    JavaScriptPostMessage(request::CreateConsoleLog(
+        file_system_id, request_id, src_file, src_line, src_func, message));
+  }
+
  private:
   // Posts a message to JavaScript. This is prone to races in case of using
   // NaCl instead of PNaCl. See crbug.com/413513.
diff --git a/unpacker/cpp/request.cc b/unpacker/cpp/request.cc
index d657b65..443e9bf 100644
--- a/unpacker/cpp/request.cc
+++ b/unpacker/cpp/request.cc
@@ -95,6 +95,22 @@
   return request;
 }
 
+pp::VarDictionary request::CreateConsoleLog(
+    const std::string& file_system_id,
+    const std::string& request_id,
+    const std::string& src_file,
+    int src_line,
+    const std::string& src_func,
+    const std::string& message) {
+  pp::VarDictionary request =
+      CreateBasicRequest(CONSOLE_LOG, file_system_id, request_id);
+  request.Set(request::key::kSrcFile, src_file);
+  request.Set(request::key::kSrcLine, src_line);
+  request.Set(request::key::kSrcFunc, src_func);
+  request.Set(request::key::kMessage, message);
+  return request;
+}
+
 int64_t request::GetInt64FromString(const pp::VarDictionary& dictionary,
                                     const std::string& request_key) {
   std::stringstream ss_int64(dictionary.Get(request_key).AsString());
diff --git a/unpacker/cpp/request.h b/unpacker/cpp/request.h
index afc644f..e24225c 100644
--- a/unpacker/cpp/request.h
+++ b/unpacker/cpp/request.h
@@ -40,6 +40,10 @@
                                                   // pp::VarArrayBuffer.
 const char kHasMoreData[] = "has_more_data";      // Should be a bool.
 const char kPassphrase[] = "passphrase";          // Should be a string.
+const char kSrcFile[] = "src_file";               // Should be a string.
+const char kSrcLine[] = "src_line";               // Should be a string.
+const char kSrcFunc[] = "src_func";               // Should be a string.
+const char kMessage[] = "message";                // Should be a string.
 
 }  // namespace key
 
@@ -61,6 +65,8 @@
   CLOSE_FILE_DONE = 12,
   READ_FILE = 13,
   READ_FILE_DONE = 14,
+  CONSOLE_LOG = 15,
+  CONSOLE_DEBUG = 16,
   FILE_SYSTEM_ERROR = -1,  // Errors specific to a file system.
 };
 
@@ -102,6 +108,14 @@
                                         const std::string& request_id,
                                         const std::string& error);
 
+pp::VarDictionary CreateConsoleLog(
+    const std::string& file_system_id,
+    const std::string& request_id,
+    const std::string& src_file,
+    int src_line,
+    const std::string& src_func,
+    const std::string& message);
+
 // Obtains a int64_t from a string value inside dictionary based on a
 // request::Key.
 int64_t GetInt64FromString(const pp::VarDictionary& dictionary,
diff --git a/unpacker/cpp/volume.cc b/unpacker/cpp/volume.cc
index b8d4dc8..8d5a3f5 100644
--- a/unpacker/cpp/volume.cc
+++ b/unpacker/cpp/volume.cc
@@ -13,6 +13,13 @@
 
 namespace {
 
+#define LOG(x) \
+  do { \
+    std::stringstream fmt; \
+    fmt << x; \
+    message_sender_->CONSOLE_LOG(file_system_id_, request_id, fmt.str()); \
+  } while (0)
+
 typedef std::map<std::string, VolumeArchive*>::const_iterator
     volume_archive_iterator;
 
diff --git a/unpacker/js/decompressor.js b/unpacker/js/decompressor.js
index 5df6ea8..787770a 100644
--- a/unpacker/js/decompressor.js
+++ b/unpacker/js/decompressor.js
@@ -218,6 +218,17 @@
       requestInProgress.onError('FAILED');
       break;
 
+    case unpacker.request.Operation.CONSOLE_LOG:
+    case unpacker.request.Operation.CONSOLE_DEBUG:
+      var src_file = data[unpacker.request.Key.SRC_FILE];
+      var src_line = data[unpacker.request.Key.SRC_LINE];
+      var src_func = data[unpacker.request.Key.SRC_FUNC];
+      var msg = data[unpacker.request.Key.MESSAGE];
+      var log = operation == unpacker.request.Operation.CONSOLE_LOG ?
+                console.log : console.debug;
+      log(src_file + ':' + src_func + ':' + src_line + ': ' + msg);
+      break;
+
     default:
       console.error('Invalid NaCl operation: ' + operation + '.');
       requestInProgress.onError('FAILED');
diff --git a/unpacker/js/request.js b/unpacker/js/request.js
index f256910..969987f 100644
--- a/unpacker/js/request.js
+++ b/unpacker/js/request.js
@@ -36,6 +36,10 @@
     READ_FILE_DATA: 'read_file_data',    // Should be an ArrayBuffer.
     HAS_MORE_DATA: 'has_more_data',      // Should be a boolean.
     PASSPHRASE: 'passphrase',            // Should be a string.
+    SRC_FILE: 'src_file',                // Should be a string.
+    SRC_LINE: 'src_line',                // Should be a int.
+    SRC_FUNC: 'src_func',                // Should be a string.
+    MESSAGE: 'message',                  // Should be a string.
   },
 
   /**
@@ -60,6 +64,8 @@
     CLOSE_FILE_DONE: 12,
     READ_FILE: 13,
     READ_FILE_DONE: 14,
+    CONSOLE_LOG: 15,
+    CONSOLE_DEBUG: 16,
     FILE_SYSTEM_ERROR: -1
   },