I have a Chromium client implementation for OS X. I would like to support double-click action on a data file which can be read and displayed inside my chromium client. For that I need to implement the method application:openFile
. This method is called long time before the application is fully initialized. For that I need to call application:openFile
after the chromium client is fully initialized and a NSWindow is present.
Which method is automatically called after chromium is fully initialized and a chrome window is available?
The class CefLoadHandler
has a method called OnLoadEnd
. This method is called, when the web-app
is loaded by the browser. But be careful! At this time the JavaScript part of the web-app
must not be already initialized. So if you are relying on full initialized JavaScript (all your JavaScript objects etc.) then you have to check this inside your JavaScript code.
See the full answer how to implement application:openFile
for Chromium Clients:
After lot of research and debugging I came up with a solution how to implement application:openFile
for Chromium based applications on OS X. First of all, there are 3 parts/layers which have to be solved.
application:openFile
Beginning with 1:
The Apple documentation for application:openFile already describes in the Discussion part, that application:openFile
is called before applicationDidFinishLaunching
. This means, that If you rely on a full initialized client (I can't imagine how's not?), you have to store the URL of the file somewhere, e.g. ivar/property in application:openFile
or like in my example below in a std::vector
of my Chromium handler
. Only if the application if fully initialized and a browser window is displayed, then you're able to directly call the Chromium handler method
that in turn calls the appropriate JavaScript function!
// ***
// application:openFile
// ***
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename {
AUApplication * clientApp = (AUApplication *)theApplication;
NSWindow* targetWindow = [clientApp findTargetWindow];
//Check if browser window is up and running
if (targetWindow) {
[self processFile:filename];
}
else {
//This method saves the file URL to open the file
//when the application+JavaScript is fully initialized
au::test::Handler* handler = au::test::Handler::GetInstance();
handler->AddPendingFile([filename UTF8String]);
}
return YES;
}
// ***
// processFile
// ***
- (BOOL)processFile:(NSString *)file
{
//This method calls the JavaScript function to open the file
std::string fileName([file UTF8String]);
au::test::Handler* handler = au::test::Handler::GetInstance();
handler->OnOpenFile(fileName);
return YES;
}
The 2 part:
On Chromium side
you have to store the file URL in a appropriate structure. I'm using std::vector
for that. The file URL is saved in the Chromium method OnLoadEnd
. Here Chromium have loaded your HTML+JavaScript parts in the browser. But be careful. The initialization of JavaScript is not done yet! In my example below I have to assign a JavaScript property to store the file URL.
// ***
// Handler::OnLoadEnd
// ***
void Handler::OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) {
if (!m_pendingOpenFiles.empty()) {
std::string file(m_pendingOpenFiles[0]);
std::cout << "Pending file for later opening: " << file << std::endl;
//This method below is calling a JavaScript function to assign
//a property `pendingFile`
OnPendingFile(file);
//Don't forget to pop the file URL afterwards
//or use another store container instead of `std::vector`
//if you don't plan to implement `application:openFiles` as well!!!
m_pendingOpenFiles.pop_back();
}
}
The 3 part:
On JavaScript side you have to check after the application initialization if the property pendingFile
is assigned or not to open the file appropriately.