Make JS app.setTimeOut() work again.

This regressed in commit 794c9b6.

BUG=551248
R=tsepez@chromium.org

Review URL: https://codereview.chromium.org/1424743006 .
diff --git a/fpdfsdk/src/fpdfformfill_embeddertest.cpp b/fpdfsdk/src/fpdfformfill_embeddertest.cpp
index 56710b9..aef1b81 100644
--- a/fpdfsdk/src/fpdfformfill_embeddertest.cpp
+++ b/fpdfsdk/src/fpdfformfill_embeddertest.cpp
@@ -6,6 +6,7 @@
 #include "../../testing/embedder_test.h"
 #include "../../testing/embedder_test_mock_delegate.h"
 #include "../../testing/embedder_test_timer_handling_delegate.h"
+#include "../../testing/test_support.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -63,3 +64,25 @@
 
   UnloadPage(page);
 }
+
+TEST_F(FPDFFormFillEmbeddertest, BUG_551248) {
+  EmbedderTestTimerHandlingDelegate delegate;
+  SetDelegate(&delegate);
+
+  EXPECT_TRUE(OpenDocument("testing/resources/bug_551248.pdf"));
+  FPDF_PAGE page = LoadPage(0);
+  EXPECT_NE(nullptr, page);
+  DoOpenActions();
+  delegate.AdvanceTime(5000);
+  UnloadPage(page);
+
+  const auto& alerts = delegate.GetAlerts();
+  ASSERT_EQ(1U, alerts.size());
+
+  std::wstring message = GetWideString(alerts[0].message);
+  std::wstring title = GetWideString(alerts[0].title);
+  EXPECT_STREQ(L"hello world", message.c_str());
+  EXPECT_STREQ(L"Alert", title.c_str());
+  EXPECT_EQ(0, alerts[0].type);
+  EXPECT_EQ(0, alerts[0].icon);
+}
diff --git a/fpdfsdk/src/javascript/JS_Object.cpp b/fpdfsdk/src/javascript/JS_Object.cpp
index 0556c4e..883ecc8 100644
--- a/fpdfsdk/src/javascript/JS_Object.cpp
+++ b/fpdfsdk/src/javascript/JS_Object.cpp
@@ -108,6 +108,7 @@
       m_bValid(true),
       m_nType(nType),
       m_dwTimeOut(dwTimeOut),
+      m_swJScript(script),
       m_pRuntime(pRuntime),
       m_pApp(pApp) {
   IFX_SystemHandler* pHandler = m_pApp->GetSysHandler();
diff --git a/samples/pdfium_test.cc b/samples/pdfium_test.cc
index 571bfcd..102f59d 100644
--- a/samples/pdfium_test.cc
+++ b/samples/pdfium_test.cc
@@ -196,19 +196,8 @@
 
 int ExampleAppAlert(IPDF_JSPLATFORM*, FPDF_WIDESTRING msg, FPDF_WIDESTRING,
                     int, int) {
-  // Deal with differences between UTF16LE and wchar_t on this platform.
-  size_t characters = 0;
-  while (msg[characters]) {
-    ++characters;
-  }
-  wchar_t* platform_string =
-      static_cast<wchar_t*>(malloc((characters + 1) * sizeof(wchar_t)));
-  for (size_t i = 0; i < characters + 1; ++i) {
-    unsigned char* ptr = (unsigned char*)&msg[i];
-    platform_string[i] = ptr[0] + 256 * ptr[1];
-  }
-  printf("Alert: %ls\n", platform_string);
-  free(platform_string);
+  std::wstring platform_string = GetWideString(msg);
+  printf("Alert: %ls\n", platform_string.c_str());
   return 0;
 }
 
diff --git a/testing/embedder_test_timer_handling_delegate.h b/testing/embedder_test_timer_handling_delegate.h
index aca4ac1..0137aae 100644
--- a/testing/embedder_test_timer_handling_delegate.h
+++ b/testing/embedder_test_timer_handling_delegate.h
@@ -7,11 +7,33 @@
 
 #include <map>
 #include <utility>
+#include <vector>
 
 #include "embedder_test.h"
 
 class EmbedderTestTimerHandlingDelegate : public EmbedderTest::Delegate {
  public:
+  struct ReceivedAlert {
+    ReceivedAlert(FPDF_WIDESTRING message_in,
+                  FPDF_WIDESTRING title_in,
+                  int type_in,
+                  int icon_in)
+        : message(message_in), title(title_in), type(type_in), icon(icon_in) {}
+
+    FPDF_WIDESTRING message;
+    FPDF_WIDESTRING title;
+    int type;
+    int icon;
+  };
+
+  int Alert(FPDF_WIDESTRING message,
+            FPDF_WIDESTRING title,
+            int type,
+            int icon) override {
+    alerts_.push_back(ReceivedAlert(message, title, type, icon));
+    return 0;
+  }
+
   int SetTimer(int msecs, TimerCallback fn) override {
     expiry_to_timer_map_.insert(std::pair<int, Timer>(
         msecs + imaginary_elapsed_msecs_, Timer(++next_timer_id_, fn)));
@@ -44,11 +66,14 @@
     }
   }
 
+  const std::vector<ReceivedAlert>& GetAlerts() const { return alerts_; }
+
  protected:
   using Timer = std::pair<int, TimerCallback>;     // ID, callback pair.
   std::multimap<int, Timer> expiry_to_timer_map_;  // Keyed by timeout.
   int next_timer_id_ = 0;
   int imaginary_elapsed_msecs_ = 0;
+  std::vector<ReceivedAlert> alerts_;
 };
 
 #endif  // TESTING_EMBEDDER_TEST_TIMER_HANDLING_DELEGATE_H_
diff --git a/testing/resources/bug_551248.in b/testing/resources/bug_551248.in
new file mode 100644
index 0000000..ad10e93
--- /dev/null
+++ b/testing/resources/bug_551248.in
@@ -0,0 +1,80 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+  /AcroForm 6 0 R
+  /Names <</JavaScript 13 0 R>>
+>>
+endobj
+{{object 2 0}} <<
+  /Type /Pages
+  /Count 1
+  /Kids [4 0 R]
+>>
+endobj
+{{object 4 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [0 0 612 792]
+  /CropBox [0 0 612 792]
+  /Resources  <<>>
+>>
+endobj
+{{object 6 0}} <<
+  /DR <<
+    /Font <</Helv 7 0 R>>
+  >>
+  /DA (/Helv 0 Tf 0 g)
+  /Fields [5 0 R]
+>>
+endobj
+{{object 7 0}} <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Helvetica
+  /Encoding /WinAnsiEncoding
+>>
+endobj
+{{object 8 0}} <<
+  /Type /XObject
+  /Subtype /Form
+  /FormType 1
+  /Matrix [1 0 0 1 0 0]
+  /BBox [0 0 75.907 28.472]
+  /Resources  <<
+    /Font <</FXF0 7 0 R>>
+  >>
+>>
+stream
+q
+Q
+
+
+endstream
+endobj
+{{object 11 0}} <<
+  /Type /Action
+  /S /JavaScript
+  /JS 50 0 R
+>>
+endobj
+{{object 13 0}} <<
+  /Names [(startDelay) 11 0 R]
+>>
+endobj
+{{object 50 0}} <<
+>>
+stream
+function startDelay()
+{
+  app.alert("hello world");
+}
+app.setTimeOut("startDelay()", 3000);
+endstream
+endobj
+{{xref}}
+trailer <<
+  /Root 1 0 R
+>>
+{{startxref}}
+%%EOF
diff --git a/testing/resources/bug_551248.pdf b/testing/resources/bug_551248.pdf
new file mode 100644
index 0000000..cca1872
--- /dev/null
+++ b/testing/resources/bug_551248.pdf
@@ -0,0 +1,134 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /Type /Catalog
+  /Pages 2 0 R
+  /AcroForm 6 0 R
+  /Names <</JavaScript 13 0 R>>
+>>
+endobj
+2 0 obj <<
+  /Type /Pages
+  /Count 1
+  /Kids [4 0 R]
+>>
+endobj
+4 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [0 0 612 792]
+  /CropBox [0 0 612 792]
+  /Resources  <<>>
+>>
+endobj
+6 0 obj <<
+  /DR <<
+    /Font <</Helv 7 0 R>>
+  >>
+  /DA (/Helv 0 Tf 0 g)
+  /Fields [5 0 R]
+>>
+endobj
+7 0 obj <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Helvetica
+  /Encoding /WinAnsiEncoding
+>>
+endobj
+8 0 obj <<
+  /Type /XObject
+  /Subtype /Form
+  /FormType 1
+  /Matrix [1 0 0 1 0 0]
+  /BBox [0 0 75.907 28.472]
+  /Resources  <<
+    /Font <</FXF0 7 0 R>>
+  >>
+>>
+stream
+q
+Q
+
+
+endstream
+endobj
+11 0 obj <<
+  /Type /Action
+  /S /JavaScript
+  /JS 50 0 R
+>>
+endobj
+13 0 obj <<
+  /Names [(startDelay) 11 0 R]
+>>
+endobj
+50 0 obj <<
+>>
+stream
+function startDelay()
+{
+  app.alert("hello world");
+}
+app.setTimeOut("startDelay()", 3000);
+endstream
+endobj
+xref
+0 51
+0000000000 65535 f 
+0000000015 00000 n 
+0000000118 00000 n 
+0000000000 65535 f 
+0000000181 00000 n 
+0000000000 65535 f 
+0000000302 00000 n 
+0000000404 00000 n 
+0000000509 00000 n 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000701 00000 n 
+0000000000 65535 f 
+0000000769 00000 n 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000822 00000 n 
+trailer <<
+  /Root 1 0 R
+>>
+startxref
+954
+%%EOF
diff --git a/testing/test_support.cpp b/testing/test_support.cpp
index 611ba5d..4923299 100644
--- a/testing/test_support.cpp
+++ b/testing/test_support.cpp
@@ -98,6 +98,22 @@
   return buffer;
 }
 
+std::wstring GetWideString(FPDF_WIDESTRING wstr) {
+  if (!wstr)
+    return nullptr;
+
+  size_t characters = 0;
+  while (wstr[characters])
+    ++characters;
+
+  std::wstring platform_string(characters, L'\0');
+  for (size_t i = 0; i < characters + 1; ++i) {
+    const unsigned char* ptr = reinterpret_cast<const unsigned char*>(&wstr[i]);
+    platform_string[i] = ptr[0] + 256 * ptr[1];
+  }
+  return platform_string;
+}
+
 #ifdef PDF_ENABLE_V8
 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
 bool InitializeV8ForPDFium(const std::string& exe_path,
diff --git a/testing/test_support.h b/testing/test_support.h
index 1018421..4bb88db 100644
--- a/testing/test_support.h
+++ b/testing/test_support.h
@@ -8,6 +8,8 @@
 #include <stdlib.h>
 #include <string>
 
+#include "../public/fpdfview.h"
+
 #ifdef PDF_ENABLE_V8
 #include "v8/include/libplatform/libplatform.h"
 #include "v8/include/v8.h"
@@ -16,6 +18,10 @@
 // Reads the entire contents of a file into a newly malloc'd buffer.
 char* GetFileContents(const char* filename, size_t* retlen);
 
+// Converts a FPDF_WIDESTRING to a std::wstring.
+// Deals with differences between UTF16LE and wchar_t.
+std::wstring GetWideString(FPDF_WIDESTRING wstr);
+
 #ifdef PDF_ENABLE_V8
 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
 bool InitializeV8ForPDFium(const std::string& exe_path,