Javascript extension registration problem

Do not post support requests, bug reports or feature requests. Discuss CEF here. Non-CEF related discussion goes in General Discussion!

Javascript extension registration problem

Postby forhappy » Wed Jul 01, 2015 6:44 pm

Hi, I have a problem about javascript extension registration problem when I using CEF in a MFC dialog based application, here is the description:

I have make a javascript extension in OnWebKitInitialized,
Code: Select all
void CSimpleBrowserApp::OnWebKitInitialized() {
    // Register the aot shell extension.

    std::string extension_code = "var aotshell;if(!aotshell){aotshell={}}if(!aotshell.fs){aotshell.fs={}}if(!aotshell.app){aotshell.app={}}...more code here";

    CefRefPtr<CefV8Handler> handler(new CShellExtensionHandler(this));
    CefRegisterExtension("shell", extension_code, handler);

    RenderDelegateSet::iterator it = render_delegates_.begin();
    for (; it != render_delegates_.end(); ++it)
        (*it)->OnWebKitInitialized(this);
}


CShellExtensionHandler send handler message to the browser process and has the following implementation:
Code: Select all
class CShellExtensionHandler : public CefV8Handler {
  public:
    explicit CShellExtensionHandler(CefRefPtr<CBrowserApp> client_app)
        : client_app_(client_app)
        , messageId(0) {
    }
    virtual bool Execute(const CefString& name,
                         CefRefPtr<CefV8Value> object,
                         const CefV8ValueList& arguments,
                         CefRefPtr<CefV8Value>& retval,
                         CefString& exception) {

        if (name == "XXXXXXXXX") {
            // Whenever a native function is called, CShellExtensionHandler::Execute() is invoked.
            // This code runs in the render process, so only the most trivial extension code should be executed here.
            //retval = CefV8Value::CreateDouble(client_app_->XXXXXXXXX());
        } else {
            // Pass all messages to the browser process.
            CefRefPtr<CefBrowser> browser = CefV8Context::GetCurrentContext()->GetBrowser();
            if (!browser.get()) {
                // If we don't have a browser, we can't handle the command.
                return false;
            }
            CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create(name);
            CefRefPtr<CefListValue> messageArgs = message->GetArgumentList();
            // The first argument must be a callback function
            if (arguments.size() > 0 && !arguments[0]->IsFunction()) {
                std::string functionName = name;
                fprintf(stderr, "Function called without callback param: %s\n", functionName.c_str());
                return false;
            }
            if (arguments.size() > 0) {
                // The first argument is the message id
                client_app_->AddCallback(messageId, CefV8Context::GetCurrentContext(), arguments[0]);
                CefSetListValue(messageArgs, 0, CefV8Value::CreateInt(messageId));
            }
            // Pass the rest of the arguments
            for (unsigned int i = 1; i < arguments.size(); i++)
                CefSetListValue(messageArgs, i, arguments[i]);
            browser->SendProcessMessage(PID_BROWSER, message);
            messageId++;
        }
        return true;
    }
  private:
    CefRefPtr<CBrowserApp> client_app_;
    int32 messageId;
    IMPLEMENT_REFCOUNTING(CShellExtensionHandler);
};


In CBrowserHandler::OnProcessMessageReceived I handled the message and run the native code for the registered javascript function, once the native code is done, send callback message to the render process, and in the last step CBrowserApp::OnProcessMessageReceived will handle the callback of the registered javascript function if there is any.
The whole story is described in https://github.com/adobe/brackets-shell/wiki/Writing-V8-Extensions

Ok, here comes my question, when I using my CBrowserApp and CBrowserHandler in a MFC dialog based application and set appSettings.multi_threaded_message_loop = true;(Using MFC message loop) I cannot call the javascript extension code in the page that loaded in, here is the page example:
Code: Select all
<html>
   <head>
      <script>
         function on_btn_cef_js_showOSFolder()
         {
            alert("invoke: on_btn_cef_js_showOSFolder()");
            aotshell.app.showOSFolder("c:\\", null);
            alert("invoke: on_btn_cef_js_showOSFolder() done");
         }
      </script>
   </head>
   <body>
      <input type="button" value="cef js test" onclick="on_btn_cef_js_showOSFolder()">
   </body>
</html>

The error message in the debug.log is:
[0701/145015:INFO:CONSOLE(7)] "Uncaught ReferenceError: aotshell is not defined", source: file:///C:/Users/forhappy/Documents/cef_js_showOSFolder.html (7)


But on the other hand, if I use the following demo to load the page the extension javascript can be called normally:
Code: Select all
int APIENTRY wWinMain(HINSTANCE hInstance,
                      HINSTANCE hPrevInstance,
                      LPTSTR    lpCmdLine,
                      int       nCmdShow) {
  UNREFERENCED_PARAMETER(hPrevInstance);
  UNREFERENCED_PARAMETER(lpCmdLine);

  // Provide CEF with command-line arguments.
  CefMainArgs main_args(hInstance);

  CefRefPtr<CBrowserApp> app(new CBrowserApp);

  int exit_code = CefExecuteProcess(main_args, app.get());
  if (exit_code >= 0) {
    // The sub-process has completed so return here.
    return exit_code;
  }

  // Specify CEF global settings here.
  CefSettings settings;

  // Initialize CEF.
  CefInitialize(main_args, settings, app.get());


     CefWindowInfo window_info;

#if defined(OS_WIN)
   window_info.SetAsPopup(NULL, "Browser");
#endif
   // SimpleHandler implements browser-level callbacks.
   CefRefPtr<CBrowserHandler> handler(new CBrowserHandler());
   
   // Specify CEF browser settings here.
   CefBrowserSettings browser_settings;
   
   std::string url = "file://C:\\Users\\forhappy\\Documents\\cef_js_showOSFolder.html";
   
   // Create the first browser window.
   CefBrowserHost::CreateBrowser(window_info, handler.get(), url,
                                browser_settings, NULL);

  CefRunMessageLoop();

  CefShutdown();

  return 0;
}


The only difference is in the first example I use MFC message loop and in the second example I use CEF message loop, the javascript extension code are the same, but the first example failed to call javasript extension code and the second one did the right thing I expected, what is the difference, can anybody help me ?

Thanks very much ;-)
forhappy
Newbie
 
Posts: 6
Joined: Tue Mar 03, 2015 12:16 am

Re: Javascript extension registration problem

Postby forhappy » Thu Jul 02, 2015 9:22 am

I fixed the problem myself ;-)
forhappy
Newbie
 
Posts: 6
Joined: Tue Mar 03, 2015 12:16 am


Return to CEF Discussion

Who is online

Users browsing this forum: No registered users and 23 guests