Browse Source

Merge pull request #692 from uWebKit/JME-ATOMIC-WEBVIEWPROPERTIES

Adding WebView global properties
JoshEngebretson 9 years ago
parent
commit
53bc8db2d0

+ 66 - 0
Source/AtomicWebView/Internal/WebAppBrowser.cpp

@@ -20,8 +20,10 @@
 // THE SOFTWARE.
 // THE SOFTWARE.
 //
 //
 
 
+#include <Atomic/IO/Log.h>
 
 
 #include "WebAppBrowser.h"
 #include "WebAppBrowser.h"
+#include "../WebBrowserHost.h"
 
 
 namespace Atomic
 namespace Atomic
 {
 {
@@ -42,5 +44,69 @@ void WebAppBrowser::OnContextInitialized()
     CefBrowserProcessHandler::OnContextInitialized();
     CefBrowserProcessHandler::OnContextInitialized();
 }
 }
 
 
+bool WebAppBrowser::CreateGlobalProperties(CefRefPtr<CefDictionaryValue>& globalProps)
+{
+
+    // Get a copy global properties
+    GlobalPropertyMap props = WebBrowserHost::GetGlobalProperties();
+
+    if (props.Empty())
+        return false;
+
+    GlobalPropertyMap::ConstIterator itr = props.Begin();
+
+    // populate with globals args
+    globalProps = CefDictionaryValue::Create();
+
+    while (itr != props.End())
+    {
+        HashMap<String, Variant>::ConstIterator pitr = itr->second_.Begin();
+
+        const String& globalVar = itr->first_;
+
+        CefRefPtr<CefDictionaryValue> kprops = CefDictionaryValue::Create();
+
+        while (pitr != itr->second_.End())
+        {
+            const String& propertyName = pitr->first_;
+            const Variant& value = pitr->second_;
+
+            if (value.GetType() == VAR_INT || value.GetType() == VAR_FLOAT || value.GetType() == VAR_DOUBLE)
+            {
+                kprops->SetDouble(propertyName.CString(), value.GetDouble());
+            }
+            else if (value.GetType() == VAR_BOOL)
+            {
+                kprops->SetBool(propertyName.CString(), value.GetBool());
+            }
+            else if (value.GetType() == VAR_STRING)
+            {
+                kprops->SetString(propertyName.CString(), value.GetString().CString());
+            }
+
+
+            pitr++;
+        }
+
+        globalProps->SetDictionary(globalVar.CString(), kprops);
+
+        itr++;
+    }
+
+    return true;
+
+}
+
+void WebAppBrowser::OnRenderProcessThreadCreated(CefRefPtr<CefListValue> extra_info)
+{
+    // We're not on main thread here, we're on IO thread
+    CefRefPtr<CefDictionaryValue> globalProps;
+    if (CreateGlobalProperties(globalProps))
+    {
+        extra_info->SetDictionary(0, globalProps);
+    }
+
+}
+
 
 
 }
 }

+ 4 - 1
Source/AtomicWebView/Internal/WebAppBrowser.h

@@ -42,9 +42,12 @@ public:
         return this;
         return this;
     }
     }
 
 
+    static bool CreateGlobalProperties(CefRefPtr<CefDictionaryValue>& globalProps);
+
     // CefBrowserProcessHandler methods.
     // CefBrowserProcessHandler methods.
-    void OnContextInitialized() OVERRIDE;
+    virtual void OnContextInitialized() OVERRIDE;
 
 
+    virtual void OnRenderProcessThreadCreated(CefRefPtr<CefListValue> extra_info) OVERRIDE;
 
 
 private:
 private:
 
 

+ 89 - 0
Source/AtomicWebView/Internal/WebAppRenderer.cpp

@@ -36,6 +36,8 @@ class WebRenderDelegate : public WebAppRenderer::Delegate
 
 
 public:
 public:
 
 
+    static CefRefPtr<CefDictionaryValue> globalProperties_;
+
     WebRenderDelegate()
     WebRenderDelegate()
         : last_node_is_editable_(false)
         : last_node_is_editable_(false)
     {
     {
@@ -52,12 +54,91 @@ public:
         message_router_ = CefMessageRouterRendererSide::Create(config);
         message_router_ = CefMessageRouterRendererSide::Create(config);
     }
     }
 
 
+    virtual void OnRenderThreadCreated(CefRefPtr<WebAppRenderer> app,
+                                       CefRefPtr<CefListValue> extra_info) OVERRIDE
+    {
+        // extra info comes from void WebAppBrowser::OnRenderProcessThreadCreated(CefRefPtr<CefListValue> extra_info)
+
+        if (extra_info->GetSize() > 0)
+        {
+            // index 0 is global properties
+            globalProperties_ = extra_info->GetDictionary(0)->Copy(false);
+        }
+
+    }
+
+    virtual bool OnBeforeNavigation(CefRefPtr<WebAppRenderer> app,
+                                    CefRefPtr<CefBrowser> browser,
+                                    CefRefPtr<CefFrame> frame,
+                                    CefRefPtr<CefRequest> request,
+                                    cef_navigation_type_t navigation_type,
+                                    bool is_redirect) OVERRIDE
+    {
+        return false;
+    }
+
+    void UpdateGlobalProperties(CefRefPtr<CefV8Context> context)
+    {
+
+        if (!globalProperties_.get())
+        {
+            return;
+        }
+
+        context->Enter();
+
+        CefDictionaryValue::KeyList keys;
+        globalProperties_->GetKeys(keys);
+
+        for (unsigned i = 0; i < keys.size(); i++)
+        {
+            const CefString& globalVarName = keys[i];
+
+            CefRefPtr<CefV8Value> globalVar = CefV8Value::CreateObject(nullptr);
+
+            CefDictionaryValue::KeyList pkeys;
+            CefRefPtr<CefDictionaryValue> props = globalProperties_->GetDictionary(globalVarName);
+            props->GetKeys(pkeys);
+
+            for (unsigned j = 0; j < pkeys.size(); j++)
+            {
+                const CefString& keyName = pkeys[j];
+
+                CefValueType type = props->GetType(keyName);
+
+                if (type == VTYPE_BOOL)
+                {
+                    globalVar->SetValue(keyName, CefV8Value::CreateBool(props->GetBool(keyName)), V8_PROPERTY_ATTRIBUTE_NONE);
+                }
+                else if (type == VTYPE_DOUBLE)
+                {
+                    globalVar->SetValue(keyName, CefV8Value::CreateDouble(props->GetDouble(keyName)), V8_PROPERTY_ATTRIBUTE_NONE);
+                }
+                else if (type == VTYPE_STRING)
+                {
+                    globalVar->SetValue(keyName, CefV8Value::CreateString(props->GetString(keyName)), V8_PROPERTY_ATTRIBUTE_NONE);
+                }
+            }
+
+            context->GetGlobal()->SetValue(globalVarName, globalVar, V8_PROPERTY_ATTRIBUTE_NONE);
+        }
+
+        context->Exit();
+    }
+
+    virtual void OnBrowserCreated(CefRefPtr<WebAppRenderer> app,
+                                  CefRefPtr<CefBrowser> browser) OVERRIDE
+    {
+    }
+
     virtual void OnContextCreated(CefRefPtr<WebAppRenderer> app,
     virtual void OnContextCreated(CefRefPtr<WebAppRenderer> app,
                                   CefRefPtr<CefBrowser> browser,
                                   CefRefPtr<CefBrowser> browser,
                                   CefRefPtr<CefFrame> frame,
                                   CefRefPtr<CefFrame> frame,
                                   CefRefPtr<CefV8Context> context) OVERRIDE
                                   CefRefPtr<CefV8Context> context) OVERRIDE
     {
     {
         message_router_->OnContextCreated(browser,  frame, context);
         message_router_->OnContextCreated(browser,  frame, context);
+
+        UpdateGlobalProperties(context);
     }
     }
 
 
     virtual void OnContextReleased(CefRefPtr<WebAppRenderer> app,
     virtual void OnContextReleased(CefRefPtr<WebAppRenderer> app,
@@ -135,6 +216,12 @@ public:
             context->Exit();
             context->Exit();
             return true;
             return true;
         }
         }
+        else if (message_name == "atomic_set_globalproperties")
+        {
+            globalProperties_ = message->GetArgumentList()->GetDictionary(0)->Copy(false);
+            UpdateGlobalProperties(browser->GetMainFrame()->GetV8Context());
+            return true;
+        }
 
 
         return message_router_->OnProcessMessageReceived(
         return message_router_->OnProcessMessageReceived(
                     browser, source_process, message);
                     browser, source_process, message);
@@ -149,6 +236,8 @@ private:
     IMPLEMENT_REFCOUNTING(WebRenderDelegate);
     IMPLEMENT_REFCOUNTING(WebRenderDelegate);
 };
 };
 
 
+CefRefPtr<CefDictionaryValue> WebRenderDelegate::globalProperties_;
+
 
 
 WebAppRenderer::WebAppRenderer() {
 WebAppRenderer::WebAppRenderer() {
 }
 }

+ 34 - 0
Source/AtomicWebView/WebBrowserHost.cpp

@@ -37,6 +37,7 @@
 
 
 #include "Internal/WebAppBrowser.h"
 #include "Internal/WebAppBrowser.h"
 
 
+#include "WebViewEvents.h"
 #include "WebSchemeHandler.h"
 #include "WebSchemeHandler.h"
 #include "WebClient.h"
 #include "WebClient.h"
 #include "WebBrowserHost.h"
 #include "WebBrowserHost.h"
@@ -94,6 +95,9 @@ private:
 
 
 };
 };
 
 
+GlobalPropertyMap WebBrowserHost::globalProperties_;
+WeakPtr<WebBrowserHost> WebBrowserHost::instance_;
+
 WebBrowserHost::WebBrowserHost(Context* context) : Object (context)
 WebBrowserHost::WebBrowserHost(Context* context) : Object (context)
 {
 {
 
 
@@ -139,14 +143,44 @@ WebBrowserHost::WebBrowserHost(Context* context) : Object (context)
 
 
     SubscribeToEvent(E_UPDATE, HANDLER(WebBrowserHost, HandleUpdate));
     SubscribeToEvent(E_UPDATE, HANDLER(WebBrowserHost, HandleUpdate));
 
 
+    instance_ = this;
+
 }
 }
 
 
 WebBrowserHost::~WebBrowserHost()
 WebBrowserHost::~WebBrowserHost()
 {
 {
+    instance_ = 0;
     CefClearSchemeHandlerFactories();
     CefClearSchemeHandlerFactories();
     CefShutdown();
     CefShutdown();
 }
 }
 
 
+void WebBrowserHost::SetGlobalBoolProperty(const String& globalVar, const String& property, bool value)
+{
+    Variant v(value);
+    SetGlobalProperty(globalVar, property, v);
+}
+
+void WebBrowserHost::SetGlobalStringProperty(const String& globalVar, const String& property, const String& value)
+{
+    Variant v(value);
+    SetGlobalProperty(globalVar, property, v);
+}
+
+void WebBrowserHost::SetGlobalNumberProperty(const String& globalVar, const String& property, double value)
+{
+    Variant v(value);
+    SetGlobalProperty(globalVar, property, v);
+}
+
+void WebBrowserHost::SetGlobalProperty(const String& globalVar, const String &property, Variant& value)
+{
+    globalProperties_[globalVar][property] = value;
+
+    if (!instance_.NotNull())
+        instance_->SendEvent(E_WEBVIEWGLOBALPROPERTIESCHANGED);
+}
+
+
 void WebBrowserHost::HandleUpdate(StringHash eventType, VariantMap& eventData)
 void WebBrowserHost::HandleUpdate(StringHash eventType, VariantMap& eventData)
 {
 {
     CefDoMessageLoopWork();
     CefDoMessageLoopWork();

+ 14 - 0
Source/AtomicWebView/WebBrowserHost.h

@@ -30,6 +30,7 @@ namespace Atomic
 class WebBrowserHostPrivate;
 class WebBrowserHostPrivate;
 class WebClient;
 class WebClient;
 
 
+typedef HashMap<String, HashMap<String, Variant>> GlobalPropertyMap;
 
 
 /// Browser host subsystem, responsible for initializing CEF
 /// Browser host subsystem, responsible for initializing CEF
 class ATOMIC_API WebBrowserHost : public Object
 class ATOMIC_API WebBrowserHost : public Object
@@ -42,12 +43,25 @@ public:
     /// Destruct.
     /// Destruct.
     virtual ~WebBrowserHost();
     virtual ~WebBrowserHost();
 
 
+    /// Set global property object values, available as read only on page
+    static void SetGlobalBoolProperty(const String& globalVar, const String& property, bool value);
+    static void SetGlobalStringProperty(const String& globalVar, const String& property, const String& value);
+    static void SetGlobalNumberProperty(const String& globalVar, const String& property, double value);
+
+    static const GlobalPropertyMap& GetGlobalProperties() { return globalProperties_; }
+
 private:
 private:
 
 
     void HandleUpdate(StringHash eventType, VariantMap& eventData);
     void HandleUpdate(StringHash eventType, VariantMap& eventData);
 
 
+    static void SetGlobalProperty(const String& globalVar, const String& property, Variant& value);
+
     WebBrowserHostPrivate* d_;
     WebBrowserHostPrivate* d_;
 
 
+    static WeakPtr<WebBrowserHost> instance_;
+
+    static GlobalPropertyMap globalProperties_;
+
 };
 };
 
 
 }
 }

+ 62 - 0
Source/AtomicWebView/WebClient.cpp

@@ -20,6 +20,11 @@
 // THE SOFTWARE.
 // THE SOFTWARE.
 //
 //
 
 
+#ifdef ATOMIC_PLATFORM_WINDOWS
+#include <windows.h>
+#undef LoadString
+#endif
+
 #include <include/cef_app.h>
 #include <include/cef_app.h>
 #include <include/cef_client.h>
 #include <include/cef_client.h>
 #include <include/cef_browser.h>
 #include <include/cef_browser.h>
@@ -35,6 +40,8 @@
 
 
 #include <Atomic/Graphics/Graphics.h>
 #include <Atomic/Graphics/Graphics.h>
 
 
+#include "Internal/WebAppBrowser.h"
+
 #include "WebBrowserHost.h"
 #include "WebBrowserHost.h"
 #include "WebMessageHandler.h"
 #include "WebMessageHandler.h"
 #include "WebClient.h"
 #include "WebClient.h"
@@ -129,6 +136,11 @@ public:
 
 
 
 
     // CefRequestHandler methods
     // CefRequestHandler methods
+
+    void OnRenderViewReady(CefRefPtr<CefBrowser> browser) OVERRIDE
+    {
+    }
+
     bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
     bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
                         CefRefPtr<CefFrame> frame,
                         CefRefPtr<CefFrame> frame,
                         CefRefPtr<CefRequest> request,
                         CefRefPtr<CefRequest> request,
@@ -137,6 +149,7 @@ public:
         CEF_REQUIRE_UI_THREAD();
         CEF_REQUIRE_UI_THREAD();
 
 
         browserSideRouter_->OnBeforeBrowse(browser, frame);
         browserSideRouter_->OnBeforeBrowse(browser, frame);
+
         return false;
         return false;
 
 
     }
     }
@@ -425,6 +438,8 @@ private:
 WebClient::WebClient(Context* context) : Object(context)
 WebClient::WebClient(Context* context) : Object(context)
 {
 {
     d_ = new WebClientPrivate(this);
     d_ = new WebClientPrivate(this);
+
+    SubscribeToEvent(E_WEBVIEWGLOBALPROPERTIESCHANGED, HANDLER(WebClient, HandleWebViewGlobalPropertiesChanged));
 }
 }
 
 
 WebClient::~WebClient()
 WebClient::~WebClient()
@@ -712,6 +727,23 @@ void WebClient::LoadURL(const String& url)
 
 
 }
 }
 
 
+void WebClient::LoadString(const String& source, const String& url)
+{
+    if (!d_->browser_.get())
+    {
+        return;
+    }
+
+    // We need to make sure global properties are updated when loading web content from source string
+    // This is handled differently internally then we requests
+    WebClient::UpdateGlobalProperties();
+
+    CefString _source(source.CString());
+    d_->browser_->GetMainFrame()->LoadString(_source, url.CString());
+
+}
+
+
 void WebClient::GoBack()
 void WebClient::GoBack()
 {
 {
     if (!d_->browser_.get())
     if (!d_->browser_.get())
@@ -825,6 +857,36 @@ bool WebClient::CreateBrowser(const String& initialURL, int width, int height)
     return result;
     return result;
 }
 }
 
 
+void WebClient::UpdateGlobalProperties()
+{
+    if (!d_->browser_.get())
+        return;
+
+    CefRefPtr<CefDictionaryValue> globalProps;
+    if (!WebAppBrowser::CreateGlobalProperties(globalProps))
+        return;
+
+    // Create the message object.
+    CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create("atomic_set_globalproperties");
+
+    // Retrieve the argument list object.
+    CefRefPtr<CefListValue> args = msg->GetArgumentList();
+
+    args->SetDictionary(0, globalProps);
+
+    // Send the process message to the render process.
+    if (!d_->browser_->SendProcessMessage(PID_RENDERER, msg))
+    {
+        LOGERROR("WebClient::UpdateGlobalProperties - Failed to send message");
+    }
+
+}
+
+void WebClient::HandleWebViewGlobalPropertiesChanged(StringHash eventType, VariantMap& eventData)
+{
+    UpdateGlobalProperties();
+}
+
 void WebClient::SetSize(int width, int height)
 void WebClient::SetSize(int width, int height)
 {
 {
     if (renderHandler_.Null())
     if (renderHandler_.Null())

+ 7 - 0
Source/AtomicWebView/WebClient.h

@@ -110,6 +110,9 @@ public:
     /// Load the specified url into the main frame of the browser
     /// Load the specified url into the main frame of the browser
     void LoadURL(const String& url);
     void LoadURL(const String& url);
 
 
+    /// Load html source into main frame of browser
+    void LoadString(const String& source, const String &url = "http://localcontent/");
+
     /// Go back in page history
     /// Go back in page history
     void GoBack();
     void GoBack();
     /// Go forward in page history
     /// Go forward in page history
@@ -126,6 +129,10 @@ public:
 
 
 private:
 private:
 
 
+    void HandleWebViewGlobalPropertiesChanged(StringHash eventType, VariantMap& eventData);
+
+    void UpdateGlobalProperties();
+
     void WasResized();
     void WasResized();
 
 
     void EvalJavaScriptResult(unsigned evalID, bool result, const String& value);
     void EvalJavaScriptResult(unsigned evalID, bool result, const String& value);

+ 5 - 0
Source/AtomicWebView/WebKeyboardMac.cpp

@@ -100,6 +100,11 @@ bool ConvertKeyEvent(Input* input, const StringHash eventType, VariantMap& event
 
 
     bool superdown = input->GetKeyDown(KEY_LGUI) || input->GetKeyDown(KEY_RGUI);
     bool superdown = input->GetKeyDown(KEY_LGUI) || input->GetKeyDown(KEY_RGUI);
 
 
+    if (!superdown && eventData.Contains("ForceSuperDown"))
+    {
+        superdown = eventData["ForceSuperDown"].GetBool();
+    }
+
     if (superdown)
     if (superdown)
         keyEvent.modifiers |= EVENTFLAG_COMMAND_DOWN;
         keyEvent.modifiers |= EVENTFLAG_COMMAND_DOWN;
 
 

+ 4 - 0
Source/AtomicWebView/WebViewEvents.h

@@ -73,6 +73,10 @@ EVENT(E_WEBVIEWJSEVALRESULT, WebViewJSEvalResult)
     PARAM(P_VALUE, Value);   // String (sucess: eval's value, error: exception message)
     PARAM(P_VALUE, Value);   // String (sucess: eval's value, error: exception message)
 }
 }
 
 
+/// WebView load state change
+EVENT(E_WEBVIEWGLOBALPROPERTIESCHANGED, WebViewGlobalPropertiesChanged)
+{
+}
 
 
 /// WebView title change
 /// WebView title change
 EVENT(E_WEBMESSAGE, WebMessage)
 EVENT(E_WEBMESSAGE, WebMessage)

+ 4 - 2
Source/ToolCore/JSBind/JSBHeaderVisitor.h

@@ -311,8 +311,10 @@ public:
                     if (arg->hasInitializer())
                     if (arg->hasInitializer())
                     {
                     {
                         ftype->initializer_ = arg->initializer()->chars();
                         ftype->initializer_ = arg->initializer()->chars();
-                        if (ftype->initializer_.StartsWith("\\"))
+
+                        if (arg->initializer()->_quotedString)
                             ftype->initializer_ = "\"" + ftype->initializer_ + "\"";
                             ftype->initializer_ = "\"" + ftype->initializer_ + "\"";
+
                     }
                     }
 
 
                     jfunction->AddParameter(ftype);
                     jfunction->AddParameter(ftype);
@@ -425,7 +427,7 @@ public:
         }
         }
 
 
         if (type->isIntegerType() || _unsigned)
         if (type->isIntegerType() || _unsigned)
-        {            
+        {
             module_->RegisterConstant(getNameString(decl->name()).CString(), value, JSBPrimitiveType::Int, _unsigned);
             module_->RegisterConstant(getNameString(decl->name()).CString(), value, JSBPrimitiveType::Int, _unsigned);
         }
         }
         else
         else

+ 4 - 0
Source/ToolCore/JSBind/cplusplus/Lexer.cpp

@@ -773,7 +773,11 @@ void Lexer::scanUntilQuote(Token *tok, unsigned char quote)
         yyinp();
         yyinp();
 
 
     if (control())
     if (control())
+    {
         tok->string = control()->stringLiteral(yytext, yylen);
         tok->string = control()->stringLiteral(yytext, yylen);
+        if (quote == '"')
+            ((StringLiteral *)tok->string)->_quotedString = true;
+    }
 }
 }
 
 
 void Lexer::scanNumericLiteral(Token *tok)
 void Lexer::scanNumericLiteral(Token *tok)

+ 5 - 1
Source/ToolCore/JSBind/cplusplus/Literals.h

@@ -67,8 +67,12 @@ class CPLUSPLUS_EXPORT StringLiteral: public Literal
 {
 {
 public:
 public:
     StringLiteral(const char *chars, unsigned size)
     StringLiteral(const char *chars, unsigned size)
-        : Literal(chars, size)
+        : Literal(chars, size), _quotedString(false)
     { }
     { }
+
+    // ATOMIC BEGIN
+    bool _quotedString;
+    // ATOMIC END
 };
 };
 
 
 class CPLUSPLUS_EXPORT NumericLiteral: public Literal
 class CPLUSPLUS_EXPORT NumericLiteral: public Literal