Extend the Fuchsia WebKit WebView

This exposes:
 - the DidFinishLoad callback
 - the stringByEvaluatingJavaScriptFromString()

Change-Id: Ide423d049452c37d55d30c44ab235197f4d2482c
diff --git a/Source/WebKit/fuchsia/WebCoreSupport/WebFrameLoaderClient.cpp b/Source/WebKit/fuchsia/WebCoreSupport/WebFrameLoaderClient.cpp
index 5b0edca..804a7bf 100644
--- a/Source/WebKit/fuchsia/WebCoreSupport/WebFrameLoaderClient.cpp
+++ b/Source/WebKit/fuchsia/WebCoreSupport/WebFrameLoaderClient.cpp
@@ -70,6 +70,11 @@
     m_title = title.string().ascii().data();
 }
 
+void WebFrameLoaderClient::dispatchDidFinishLoad()
+{
+    m_webView->dispatchDidFinishLoad();
+}
+
 ObjectContentType WebFrameLoaderClient::objectContentType(const URL&, const String&)
 {
     return ObjectContentType();
diff --git a/Source/WebKit/fuchsia/WebCoreSupport/WebFrameLoaderClient.h b/Source/WebKit/fuchsia/WebCoreSupport/WebFrameLoaderClient.h
index ea7ee29..b414f8a 100644
--- a/Source/WebKit/fuchsia/WebCoreSupport/WebFrameLoaderClient.h
+++ b/Source/WebKit/fuchsia/WebCoreSupport/WebFrameLoaderClient.h
@@ -33,6 +33,7 @@
     void dispatchDidFailLoad(const WebCore::ResourceError& error) override;
     void dispatchWillSubmitForm(PassRefPtr<WebCore::FormState>, WebCore::FramePolicyFunction) override;
     void dispatchDidReceiveTitle(const WebCore::StringWithDirection&) override;
+    void dispatchDidFinishLoad() override;
 
     bool canHandleRequest(const WebCore::ResourceRequest&) const override { return true; }
     bool canShowMIMEType(const String&) const override { return true; }
diff --git a/Source/WebKit/fuchsia/WebView.cpp b/Source/WebKit/fuchsia/WebView.cpp
index b488cc0..3268cd8 100644
--- a/Source/WebKit/fuchsia/WebView.cpp
+++ b/Source/WebKit/fuchsia/WebView.cpp
@@ -29,6 +29,7 @@
 #include <WebCore/DocumentLoader.h>
 #include <WebCore/FocusController.h>
 #include <WebCore/FrameLoadRequest.h>
+#include <WebCore/ScriptController.h>
 #include <WebCore/GraphicsContext.h>
 #include <WebCore/IntSize.h>
 #include <WebCore/LogInitialization.h>
@@ -41,6 +42,7 @@
 #include <WebCore/ResourceRequest.h>
 #include <WebCore/Settings.h>
 #include <WebCore/URLParser.h>
+#include <runtime/JSCJSValue.h>
 
 #include <WebKit/fuchsia/WebCoreSupport/WebChromeClient.h>
 #include <WebKit/fuchsia/WebCoreSupport/WebEditorClient.h>
@@ -362,6 +364,16 @@
   m_webRequestDelegate = delegate;
 }
 
+void WebView::setDidFinishLoadDelegate(DidFinishLoadDelegate delegate) {
+  m_didFinishLoadDelegate = delegate;
+}
+
+void WebView::dispatchDidFinishLoad() {
+  if (m_didFinishLoadDelegate) {
+    m_didFinishLoadDelegate();
+  }
+}
+
 void WebView::iterateEventLoop()
 {
     RunLoop::iterate();
@@ -387,3 +399,22 @@
 {
   WebCore::deleteAllCookies(NetworkStorageSession::defaultStorageSession());
 }
+
+std::string WebView::stringByEvaluatingJavaScriptFromString(
+    const std::string& script) {
+  auto& mainFrame = m_page->mainFrame();
+  WTF::String scriptString(script.data(), script.size());
+  JSC::JSValue result = mainFrame.script().executeScript(scriptString, true);
+
+  if (!result) {
+    return "";
+  }
+
+  JSC::ExecState* exec =
+      mainFrame.script().globalObject(mainThreadNormalWorld())->globalExec();
+  JSC::JSLockHolder lock(exec);
+  WTF::String resultString = result.getString(exec);
+  WTF::CString resultCString =
+      resultString.utf8(WTF::ConversionMode::LenientConversion);
+  return std::string(resultCString.data(), resultCString.length());
+}
diff --git a/Source/WebKit/fuchsia/WebView.h b/Source/WebKit/fuchsia/WebView.h
index 10fd0c8..a2b8c68 100644
--- a/Source/WebKit/fuchsia/WebView.h
+++ b/Source/WebKit/fuchsia/WebView.h
@@ -45,6 +45,7 @@
 typedef struct _cairo cairo_t;
 typedef struct _cairo_surface cairo_surface_t;
 typedef std::function<std::string(const std::string&)> WebRequestDelegate;
+typedef std::function<void()> DidFinishLoadDelegate;
 
 class WebView {
 public:
@@ -80,6 +81,9 @@
     void setWebRequestDelegate(WebRequestDelegate delegate);
     void dispatchWillSendRequest(WebCore::DocumentLoader*, unsigned long identifier, WebCore::ResourceRequest&, const WebCore::ResourceResponse& redirectResponse);
 
+    void setDidFinishLoadDelegate(DidFinishLoadDelegate delegate);
+    void dispatchDidFinishLoad();
+
     void iterateEventLoop();
 
     std::string getTitle();
@@ -91,8 +95,14 @@
     cairo_t* cairoContext() const { return m_cairoContext; }
     cairo_surface_t* cairoSurface() const { return m_cairoSurface; }
 
+    // This evaluates JS in the top-level page of the web view and returns the
+    // string form of the result. If execution fails the empty string will be
+    // returned.
+    std::string stringByEvaluatingJavaScriptFromString(const std::string& script);
+
 private:
     WebRequestDelegate m_webRequestDelegate;
+    DidFinishLoadDelegate m_didFinishLoadDelegate;
 
     void setURLInternal(const WebCore::URL& url);
     void scrollInternal(uint8_t direction, uint8_t granularity);