From 1976244aef3bf5af8be23bcc505272441dd513de Mon Sep 17 00:00:00 2001 From: Jason San Jose Date: Thu, 14 Nov 2013 09:54:07 -0800 Subject: [PATCH 1/3] Revert "Merge pull request #379 from fungl164/fungl164/chrome-live-osx-2" This reverts commit 808c31d7361862c5c5102123e48c8bdf042c7da9, reversing changes made to ea2d08e1ad85a61f61ac1c2e91a6afcdee05ab44. --- appshell/appshell_extensions_mac.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appshell/appshell_extensions_mac.mm b/appshell/appshell_extensions_mac.mm index bba5a0600..3b617836f 100644 --- a/appshell/appshell_extensions_mac.mm +++ b/appshell/appshell_extensions_mac.mm @@ -319,7 +319,7 @@ int32 OpenLiveBrowser(ExtensionString argURL, bool enableRemoteDebugging) } GoogleChromeWindow* chromeWindow = [[chromeApp windows] objectAtIndex:0]; - if (!chromeWindow || [[chromeWindow tabs] count] == 0) { + if(!chromeWindow){ // Create new LiveBrowser Window GoogleChromeWindow* chromeWindow = [[[chromeApp classForScriptingClass:@"window"] alloc] init]; [[chromeApp windows] addObject:chromeWindow]; From ec40f23f06cd8cf6b81ea6e63029ad1d314f6c63 Mon Sep 17 00:00:00 2001 From: Jason San Jose Date: Thu, 14 Nov 2013 09:54:29 -0800 Subject: [PATCH 2/3] Revert "Merge pull request #373 from fungl164/fungl164/chrome-live-osx-2" This reverts commit b8b277b6acb330f4a04b0c3a1a5bdf23b0f1076c, reversing changes made to 7ed6c3e23baf9d3a2b26368bb6e8868da56887cd. --- appshell/appshell_extensions_mac.mm | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/appshell/appshell_extensions_mac.mm b/appshell/appshell_extensions_mac.mm index 3b617836f..c88172c4e 100644 --- a/appshell/appshell_extensions_mac.mm +++ b/appshell/appshell_extensions_mac.mm @@ -151,23 +151,19 @@ void SetLiveBrowserPid(int pid) void LiveBrowserMgrMac::CloseLiveBrowserFireCallback(int valToSend) { + CefRefPtr responseArgs = m_closeLiveBrowserCallback->GetArgumentList(); + // kill the timers CloseLiveBrowserKillTimers(); // Stop listening for ws shutdown notifications RemoveWorkspaceNotifications(); - // Prepare response - if (m_closeLiveBrowserCallback) { - - CefRefPtr responseArgs = m_closeLiveBrowserCallback->GetArgumentList(); - - // Set common response args (callbackId and error) - responseArgs->SetInt(1, valToSend); - - // Send response - m_browser->SendProcessMessage(PID_RENDERER, m_closeLiveBrowserCallback); - } + // Set common response args (callbackId and error) + responseArgs->SetInt(1, valToSend); + + // Send response + m_browser->SendProcessMessage(PID_RENDERER, m_closeLiveBrowserCallback); // Clear state m_closeLiveBrowserCallback = NULL; From 8bc2ea572f21bc5c8d55e4405e0f26295862298c Mon Sep 17 00:00:00 2001 From: Jason San Jose Date: Thu, 14 Nov 2013 09:54:46 -0800 Subject: [PATCH 3/3] Revert "Merge pull request #371 from fungl164/fungl164/chrome-live-osx-2" This reverts commit 305dadc954d58cbb8f20df07f7cc95d88d9f980f, reversing changes made to 7d19cdc3666749ca1466146d0b5b493d589da9b1. --- appshell.gyp | 6 +- appshell/GoogleChrome.h | 191 ---------- appshell/appshell_extensions_mac.mm | 443 ++++-------------------- appshell/appshell_extensions_platform.h | 1 - 4 files changed, 69 insertions(+), 572 deletions(-) delete mode 100644 appshell/GoogleChrome.h diff --git a/appshell.gyp b/appshell.gyp index 84f9ee897..7f78d66b5 100755 --- a/appshell.gyp +++ b/appshell.gyp @@ -1,4 +1,4 @@ - # Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights +# Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights # reserved. Use of this source code is governed by a BSD-style license that # can be found in the LICENSE file. @@ -204,8 +204,6 @@ 'link_settings': { 'libraries': [ '$(SDKROOT)/System/Library/Frameworks/AppKit.framework', - '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', - '$(SDKROOT)/System/Library/Frameworks/ScriptingBridge.framework', '$(CONFIGURATION)/libcef.dylib', ], }, @@ -361,8 +359,6 @@ 'link_settings': { 'libraries': [ '$(SDKROOT)/System/Library/Frameworks/AppKit.framework', - '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', - '$(SDKROOT)/System/Library/Frameworks/ScriptingBridge.framework', '$(CONFIGURATION)/libcef.dylib', ], }, diff --git a/appshell/GoogleChrome.h b/appshell/GoogleChrome.h deleted file mode 100644 index 24f51aecb..000000000 --- a/appshell/GoogleChrome.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * GoogleChrome.h - */ - -#import -#import - - -@class GoogleChromeApplication, GoogleChromeWindow, GoogleChromeTab, GoogleChromeBookmarkFolder, GoogleChromeBookmarkItem; - - - -/* - * Standard Suite - */ - -// The application's top-level scripting object. -@interface GoogleChromeApplication : SBApplication - -- (SBElementArray *) windows; - -@property (copy, readonly) NSString *name; // The name of the application. -@property (readonly) BOOL frontmost; // Is this the frontmost (active) application? -@property (copy, readonly) NSString *version; // The version of the application. - -- (void) open:(NSArray *)x; // Open a document. -- (void) quit; // Quit the application. -- (BOOL) exists:(id)x; // Verify if an object exists. - -@end - -// A window. -@interface GoogleChromeWindow : SBObject - -- (SBElementArray *) tabs; - -@property (copy, readonly) NSString *name; // The full title of the window. -- (NSInteger) id; // The unique identifier of the window. -@property NSInteger index; // The index of the window, ordered front to back. -@property NSRect bounds; // The bounding rectangle of the window. -@property (readonly) BOOL closeable; // Whether the window has a close box. -@property (readonly) BOOL minimizable; // Whether the window can be minimized. -@property BOOL minimized; // Whether the window is currently minimized. -@property (readonly) BOOL resizable; // Whether the window can be resized. -@property BOOL visible; // Whether the window is currently visible. -@property (readonly) BOOL zoomable; // Whether the window can be zoomed. -@property BOOL zoomed; // Whether the window is currently zoomed. -@property (copy, readonly) GoogleChromeTab *activeTab; // Returns the currently selected tab -@property (copy) NSString *mode; // Represents the mode of the window which can be 'normal' or 'incognito', can be set only once during creation of the window. -@property NSInteger activeTabIndex; // The index of the active tab. - -- (void) saveIn:(NSURL *)in_ as:(NSString *)as; // Save an object. -- (void) close; // Close a window. -- (void) delete; // Delete an object. -- (SBObject *) duplicateTo:(SBObject *)to withProperties:(NSDictionary *)withProperties; // Copy object(s) and put the copies at a new location. -- (SBObject *) moveTo:(SBObject *)to; // Move object(s) to a new location. -- (void) print; // Print an object. -- (void) reload; // Reload a tab. -- (void) goBack; // Go Back (If Possible). -- (void) goForward; // Go Forward (If Possible). -- (void) selectAll; // Select all. -- (void) cutSelection; // Cut selected text (If Possible). -- (void) copySelection; // Copy text. -- (void) pasteSelection; // Paste text (If Possible). -- (void) undo; // Undo the last change. -- (void) redo; // Redo the last change. -- (void) stop; // Stop the current tab from loading. -- (void) viewSource; // View the HTML source of the tab. -- (id) executeJavascript:(NSString *)javascript; // Execute a piece of javascript. -- (void) enterPresentationMode; // Enter presentation mode in window. -- (void) exitPresentationMode; // Exit presentation mode in window. - -@end - - - -/* - * Chromium Suite - */ - -// The application's top-level scripting object. -@interface GoogleChromeApplication (ChromiumSuite) - -- (SBElementArray *) bookmarkFolders; - -@property (copy, readonly) GoogleChromeBookmarkFolder *bookmarksBar; // The bookmarks bar bookmark folder. -@property (copy, readonly) GoogleChromeBookmarkFolder *otherBookmarks; // The other bookmarks bookmark folder. - -@end - -// A tab. -@interface GoogleChromeTab : SBObject - -- (NSInteger) id; // Unique ID of the tab. -@property (copy, readonly) NSString *title; // The title of the tab. -@property (copy) NSString *URL; // The url visible to the user. -@property (readonly) BOOL loading; // Is loading? - -- (void) saveIn:(NSURL *)in_ as:(NSString *)as; // Save an object. -- (void) close; // Close a window. -- (void) delete; // Delete an object. -- (SBObject *) duplicateTo:(SBObject *)to withProperties:(NSDictionary *)withProperties; // Copy object(s) and put the copies at a new location. -- (SBObject *) moveTo:(SBObject *)to; // Move object(s) to a new location. -- (void) print; // Print an object. -- (void) reload; // Reload a tab. -- (void) goBack; // Go Back (If Possible). -- (void) goForward; // Go Forward (If Possible). -- (void) selectAll; // Select all. -- (void) cutSelection; // Cut selected text (If Possible). -- (void) copySelection; // Copy text. -- (void) pasteSelection; // Paste text (If Possible). -- (void) undo; // Undo the last change. -- (void) redo; // Redo the last change. -- (void) stop; // Stop the current tab from loading. -- (void) viewSource; // View the HTML source of the tab. -- (id) executeJavascript:(NSString *)javascript; // Execute a piece of javascript. -- (void) enterPresentationMode; // Enter presentation mode in window. -- (void) exitPresentationMode; // Exit presentation mode in window. - -@end - -// A bookmarks folder that contains other bookmarks folder and bookmark items. -@interface GoogleChromeBookmarkFolder : SBObject - -- (SBElementArray *) bookmarkFolders; -- (SBElementArray *) bookmarkItems; - -- (NSNumber *) id; // Unique ID of the bookmark folder. -@property (copy) NSString *title; // The title of the folder. -@property (copy, readonly) NSNumber *index; // Returns the index with respect to its parent bookmark folder - -- (void) saveIn:(NSURL *)in_ as:(NSString *)as; // Save an object. -- (void) close; // Close a window. -- (void) delete; // Delete an object. -- (SBObject *) duplicateTo:(SBObject *)to withProperties:(NSDictionary *)withProperties; // Copy object(s) and put the copies at a new location. -- (SBObject *) moveTo:(SBObject *)to; // Move object(s) to a new location. -- (void) print; // Print an object. -- (void) reload; // Reload a tab. -- (void) goBack; // Go Back (If Possible). -- (void) goForward; // Go Forward (If Possible). -- (void) selectAll; // Select all. -- (void) cutSelection; // Cut selected text (If Possible). -- (void) copySelection; // Copy text. -- (void) pasteSelection; // Paste text (If Possible). -- (void) undo; // Undo the last change. -- (void) redo; // Redo the last change. -- (void) stop; // Stop the current tab from loading. -- (void) viewSource; // View the HTML source of the tab. -- (id) executeJavascript:(NSString *)javascript; // Execute a piece of javascript. -- (void) enterPresentationMode; // Enter presentation mode in window. -- (void) exitPresentationMode; // Exit presentation mode in window. - -@end - -// An item consists of an URL and the title of a bookmark -@interface GoogleChromeBookmarkItem : SBObject - -- (NSInteger) id; // Unique ID of the bookmark item. -@property (copy) NSString *title; // The title of the bookmark item. -@property (copy) NSString *URL; // The URL of the bookmark. -@property (copy, readonly) NSNumber *index; // Returns the index with respect to its parent bookmark folder - -- (void) saveIn:(NSURL *)in_ as:(NSString *)as; // Save an object. -- (void) close; // Close a window. -- (void) delete; // Delete an object. -- (SBObject *) duplicateTo:(SBObject *)to withProperties:(NSDictionary *)withProperties; // Copy object(s) and put the copies at a new location. -- (SBObject *) moveTo:(SBObject *)to; // Move object(s) to a new location. -- (void) print; // Print an object. -- (void) reload; // Reload a tab. -- (void) goBack; // Go Back (If Possible). -- (void) goForward; // Go Forward (If Possible). -- (void) selectAll; // Select all. -- (void) cutSelection; // Cut selected text (If Possible). -- (void) copySelection; // Copy text. -- (void) pasteSelection; // Paste text (If Possible). -- (void) undo; // Undo the last change. -- (void) redo; // Redo the last change. -- (void) stop; // Stop the current tab from loading. -- (void) viewSource; // View the HTML source of the tab. -- (id) executeJavascript:(NSString *)javascript; // Execute a piece of javascript. -- (void) enterPresentationMode; // Enter presentation mode in window. -- (void) exitPresentationMode; // Exit presentation mode in window. - -@end - -@interface GoogleChromeWindow (ChromiumSuite) - -@property (readonly) BOOL presenting; // Whether the window is in presentation mode. - -@end - diff --git a/appshell/appshell_extensions_mac.mm b/appshell/appshell_extensions_mac.mm index c88172c4e..6c16d1c1e 100644 --- a/appshell/appshell_extensions_mac.mm +++ b/appshell/appshell_extensions_mac.mm @@ -25,10 +25,7 @@ #include "appshell_extensions.h" #include "native_menu_model.h" -#include "GoogleChrome.h" - #include -#include NSMutableArray* pendingOpenFiles; @@ -37,20 +34,10 @@ - (void)appTerminated:(NSNotification *)note; - (void)timeoutTimer:(NSTimer*)timer; @end -// LiveBrowser helper functions -NSRunningApplication* GetLiveBrowserApp(NSString *bundleId, int debugPort); -NSString* GetUserProfilePath() { - return [NSString stringWithFormat:@"%s%@", ClientApp::AppGetSupportDirectory().ToString().c_str(), @"/live-dev-profile"]; -} - // App ID for either Chrome or Chrome Canary (commented out) NSString *const appId = @"com.google.Chrome"; //NSString *const appId = @"com.google.Chrome.canary"; -// Live Development debug port -int const debugPort = 9222; -NSString* debugPortCommandlineArguments = [NSString stringWithFormat:@"--remote-debugging-port=%d", debugPort]; - /////////////////////////////////////////////////////////////////////////////// // LiveBrowserMgrMac @@ -64,19 +51,11 @@ - (void)timeoutTimer:(NSTimer*)timer; void CheckForChromeRunning(); void CheckForChromeRunningTimeout(); - void SetWorkspaceNotifications(int pid); - void RemoveWorkspaceNotifications(); - void CloseLiveBrowserKillTimers(); void CloseLiveBrowserFireCallback(int valToSend); - int IncrementOpenRetryCount() { return m_openLiveBrowserRetryCount++; } - void ResetOpenRetryCount() { m_openLiveBrowserRetryCount = 0; } - ChromeWindowsTerminatedObserver* GetTerminateObserver() { return m_chromeTerminateObserver; } CefRefPtr GetCloseCallback() { return m_closeLiveBrowserCallback; } - NSRunningApplication* GetLiveBrowser() { return GetLiveBrowserApp(appId, debugPort); } - int GetLiveBrowserPid() { return m_liveBrowserPid; } void SetCloseTimeoutTimer(NSTimer* closeLiveBrowserTimeoutTimer) { m_closeLiveBrowserTimeoutTimer = closeLiveBrowserTimeoutTimer; } @@ -86,30 +65,25 @@ void SetCloseCallback(CefRefPtr response) { m_closeLiveBrowserCallback = response; } void SetBrowser(CefRefPtr browser) { m_browser = browser; } - void SetLiveBrowserPid(int pid) - { m_liveBrowserPid = pid; } + private: // private so this class cannot be instantiated externally LiveBrowserMgrMac(); virtual ~LiveBrowserMgrMac(); - int m_openLiveBrowserRetryCount; NSTimer* m_closeLiveBrowserTimeoutTimer; CefRefPtr m_closeLiveBrowserCallback; CefRefPtr m_browser; ChromeWindowsTerminatedObserver* m_chromeTerminateObserver; - int m_liveBrowserPid; - static LiveBrowserMgrMac* s_instance; + static LiveBrowserMgrMac* s_instance; }; LiveBrowserMgrMac::LiveBrowserMgrMac() -: m_openLiveBrowserRetryCount(0) -, m_closeLiveBrowserTimeoutTimer(nil) -, m_chromeTerminateObserver(nil) -, m_liveBrowserPid(ERR_PID_NOT_FOUND) + : m_closeLiveBrowserTimeoutTimer(nil) + , m_chromeTerminateObserver(nil) { } @@ -117,15 +91,12 @@ void SetLiveBrowserPid(int pid) { if (s_instance) s_instance->CloseLiveBrowserKillTimers(); - - RemoveWorkspaceNotifications(); } LiveBrowserMgrMac* LiveBrowserMgrMac::GetInstance() { if (!s_instance) s_instance = new LiveBrowserMgrMac(); - return s_instance; } @@ -137,7 +108,14 @@ void SetLiveBrowserPid(int pid) bool LiveBrowserMgrMac::IsChromeRunning() { - return GetLiveBrowser() ? true : false; + NSArray *apps = [NSRunningApplication runningApplicationsWithBundleIdentifier:appId]; + for (NSUInteger i = 0; i < apps.count; i++) { + NSRunningApplication* curApp = [apps objectAtIndex:i]; + if( curApp && !curApp.terminated ) { + return true; + } + } + return false; } void LiveBrowserMgrMac::CloseLiveBrowserKillTimers() @@ -147,6 +125,12 @@ void SetLiveBrowserPid(int pid) [m_closeLiveBrowserTimeoutTimer release]; m_closeLiveBrowserTimeoutTimer = nil; } + + if (m_chromeTerminateObserver) { + [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:m_chromeTerminateObserver]; + [m_chromeTerminateObserver release]; + m_chromeTerminateObserver = nil; + } } void LiveBrowserMgrMac::CloseLiveBrowserFireCallback(int valToSend) @@ -155,10 +139,7 @@ void SetLiveBrowserPid(int pid) // kill the timers CloseLiveBrowserKillTimers(); - - // Stop listening for ws shutdown notifications - RemoveWorkspaceNotifications(); - + // Set common response args (callbackId and error) responseArgs->SetInt(1, valToSend); @@ -175,10 +156,6 @@ void SetLiveBrowserPid(int pid) if (IsChromeRunning()) return; - // Unset the LiveBrowser pid - m_liveBrowserPid = ERR_PID_NOT_FOUND; - - // Fire callback to browser CloseLiveBrowserFireCallback(NO_ERROR); } @@ -190,143 +167,55 @@ void SetLiveBrowserPid(int pid) CloseLiveBrowserFireCallback(retVal); } -void LiveBrowserMgrMac::SetWorkspaceNotifications(int PID) -{ - - // Cache the LiveBrowser pid for fast lookups + matching during termination - SetLiveBrowserPid(PID); - - // Set up workspace notifications for asynchronous Browser shutdowns - if (!GetTerminateObserver()) { - //register an observer to watch for the app terminations - SetTerminateObserver([[ChromeWindowsTerminatedObserver alloc] init]); - - [[[NSWorkspace sharedWorkspace] notificationCenter] - addObserver:GetTerminateObserver() - selector:@selector(appTerminated:) - name:NSWorkspaceDidTerminateApplicationNotification - object:nil - ]; - } -} - -void LiveBrowserMgrMac::RemoveWorkspaceNotifications() -{ - if (m_chromeTerminateObserver) { - [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:m_chromeTerminateObserver]; - [m_chromeTerminateObserver release]; - m_chromeTerminateObserver = nil; - } -} - LiveBrowserMgrMac* LiveBrowserMgrMac::s_instance = NULL; // Forward declarations for functions defined later in this file void NSArrayToCefList(NSArray* array, CefRefPtr& list); int32 ConvertNSErrorCode(NSError* error, bool isReading); -GoogleChromeApplication* GetGoogleChromeApplicationWithPid(int PID) -{ - try { - return [SBApplication applicationWithProcessIdentifier:PID]; - } - catch (...) { - return nil; - } -} int32 OpenLiveBrowser(ExtensionString argURL, bool enableRemoteDebugging) { - LiveBrowserMgrMac* liveBrowserMgr = LiveBrowserMgrMac::GetInstance(); - // Parse the arguments NSString *urlString = [NSString stringWithUTF8String:argURL.c_str()]; + NSURL *url = [NSURL URLWithString:urlString]; // Find instances of the Browser - NSRunningApplication* liveBrowser = liveBrowserMgr->GetLiveBrowser(); + NSArray *apps = [NSRunningApplication runningApplicationsWithBundleIdentifier:appId]; + NSWorkspace * ws = [NSWorkspace sharedWorkspace]; + NSUInteger launchOptions = NSWorkspaceLaunchDefault | NSWorkspaceLaunchWithoutActivation; - // Launch Browser (if not running) - if (!liveBrowser) { + // Launch Browser + if(apps.count == 0) { - NSWorkspace * ws = [NSWorkspace sharedWorkspace]; - NSURL *appURL = [ws URLForApplicationWithBundleIdentifier:appId]; - if( !appURL ) { - return ERR_NOT_FOUND; //Chrome not installed - } - // Create the configuration dictionary for launching with custom parameters. NSArray *parameters = nil; - NSString *profilePath = [NSString stringWithFormat:@"--user-data-dir=%@", GetUserProfilePath()]; - - parameters = [NSArray arrayWithObjects: - debugPortCommandlineArguments, - @"--allow-file-access-from-files", - @"--no-first-run", - @"--no-default-browser-check", - @"--temp-profile", - profilePath, - urlString, - nil]; - - NSDictionary* appConfig = [NSDictionary dictionaryWithObject:parameters forKey:NSWorkspaceLaunchConfigurationArguments]; - - NSError *error = nil; - NSUInteger launchOptions = NSWorkspaceLaunchDefault | NSWorkspaceLaunchWithoutActivation | NSWorkspaceLaunchNewInstance; - liveBrowser = [ws launchApplicationAtURL:appURL options:launchOptions configuration:appConfig error:&error]; - - // Set up workspace notifications for asynchronous Browser shutdowns - if (liveBrowser) { - liveBrowserMgr->SetWorkspaceNotifications([liveBrowser processIdentifier]); + if (enableRemoteDebugging) { + parameters = [NSArray arrayWithObjects: + @"--remote-debugging-port=9222", + @"--allow-file-access-from-files", + nil]; } - - return liveBrowser ? NO_ERROR : ERR_UNKNOWN; - } - - // A running instance of LiveBrowser was found. Let's get the corresponding GoogleChromeApplication object - GoogleChromeApplication *chromeApp = GetGoogleChromeApplicationWithPid([liveBrowser processIdentifier]); - - // Sanity check - if (!chromeApp) { - // Failed to retrieve the LiveBrowser's instance as a GoogleChromeApplication object. - // It's very likely that Chrome has been shutdown asynchronously. - - // So let's try to open a new instance recursively, first making sure we limit the - // number of retries in order to prevent infinite looping... - if (liveBrowserMgr->IncrementOpenRetryCount() > 3) { - liveBrowserMgr->ResetOpenRetryCount(); - return ERR_UNKNOWN; + else { + parameters = [NSArray arrayWithObjects: + @"--allow-file-access-from-files", + nil]; } - return OpenLiveBrowser(argURL, enableRemoteDebugging); - } - - liveBrowserMgr->ResetOpenRetryCount(); + NSMutableDictionary* appConfig = [NSDictionary dictionaryWithObject:parameters forKey:NSWorkspaceLaunchConfigurationArguments]; - // Set up workspace notifications for asynchronous Browser shutdowns - liveBrowserMgr->SetWorkspaceNotifications([liveBrowser processIdentifier]); - - // Check for existing tab (with interstitial page) in all open Chrome windows - for (GoogleChromeWindow* chromeWindow in [chromeApp windows]){ - for (GoogleChromeTab* tab in [chromeWindow tabs]) { - if ([tab.URL isEqualToString:urlString]) { - // Found and open tab with interstitial page loaded - return NO_ERROR; - } + NSURL *appURL = [ws URLForApplicationWithBundleIdentifier:appId]; + if( !appURL ) { + return ERR_NOT_FOUND; //Chrome not installed + } + NSError *error = nil; + if( ![ws launchApplicationAtURL:appURL options:launchOptions configuration:appConfig error:&error] ) { + return ERR_UNKNOWN; } } - - GoogleChromeWindow* chromeWindow = [[chromeApp windows] objectAtIndex:0]; - if(!chromeWindow){ - // Create new LiveBrowser Window - GoogleChromeWindow* chromeWindow = [[[chromeApp classForScriptingClass:@"window"] alloc] init]; - [[chromeApp windows] addObject:chromeWindow]; - chromeWindow.activeTab.URL = urlString; - [chromeWindow release]; - } else { - // Create new Tab in LiveBrowser window - GoogleChromeTab* chromeTab = [[[chromeApp classForScriptingClass:@"tab"] alloc] initWithProperties:@{@"URL": urlString}]; - [[chromeWindow tabs] addObject:chromeTab]; - [chromeTab release]; - } + + // Tell the Browser to load the url + [ws openURLs:[NSArray arrayWithObject:url] withAppBundleIdentifier:appId options:launchOptions additionalEventParamDescriptor:nil launchIdentifiers:nil]; + return NO_ERROR; } @@ -340,45 +229,40 @@ void CloseLiveBrowser(CefRefPtr browser, CefRefPtrCloseLiveBrowserFireCallback(ERR_UNKNOWN); } - // Set up new Brackets CloseLiveBrowser callbacks liveBrowserMgr->SetBrowser(browser); liveBrowserMgr->SetCloseCallback(response); - // Set up workspace shutdown notifications (in case they are not currently setup - // or have been since disabled by a previous browser shutdown notification) - liveBrowserMgr->SetWorkspaceNotifications(liveBrowserMgr->GetLiveBrowserPid()); + // Find instances of the Browser and terminate them + NSArray *apps = [NSRunningApplication runningApplicationsWithBundleIdentifier:appId]; - // Check chrome - if (!liveBrowserMgr->IsChromeRunning()) { + if (apps.count == 0) { + // No instances of Chrome found. Fire callback immediately. liveBrowserMgr->CloseLiveBrowserFireCallback(NO_ERROR); return; + } else if (apps.count > 0 && !LiveBrowserMgrMac::GetInstance()->GetTerminateObserver()) { + //register an observer to watch for the app terminations + LiveBrowserMgrMac::GetInstance()->SetTerminateObserver([[ChromeWindowsTerminatedObserver alloc] init]); + + [[[NSWorkspace sharedWorkspace] notificationCenter] + addObserver:LiveBrowserMgrMac::GetInstance()->GetTerminateObserver() + selector:@selector(appTerminated:) + name:NSWorkspaceDidTerminateApplicationNotification + object:nil + ]; } - // Get the currently active LiveBrowser session - GoogleChromeApplication* chromeApp = GetGoogleChromeApplicationWithPid(liveBrowserMgr->GetLiveBrowserPid()); - if (!chromeApp) { - // No active LiveBrowser found - liveBrowserMgr->CloseLiveBrowserFireCallback(NO_ERROR); - return; - } - - // Technically at this point we would locate the LiveBrowser window and - // close all tabs; however, the LiveDocument tab already closed by Inspector! - // and there is no way to find which window to close. - - // Do not close other windows - if ([[chromeApp windows] count] > 0 || [[[[chromeApp windows] objectAtIndex:0] tabs] count] > 0) { - liveBrowserMgr->CloseLiveBrowserFireCallback(NO_ERROR); - return; + // Iterate over open browser intances and terminate + for (NSUInteger i = 0; i < apps.count; i++) { + NSRunningApplication* curApp = [apps objectAtIndex:i]; + if( curApp && !curApp.terminated ) { + [curApp terminate]; + } } - // No more open windows found, so quit Chrome - [chromeApp quit]; - - // Set timeout timer + //start a timeout timer liveBrowserMgr->SetCloseTimeoutTimer([[NSTimer scheduledTimerWithTimeInterval:(3 * 60) - target:liveBrowserMgr->GetTerminateObserver() + target:LiveBrowserMgrMac::GetInstance()->GetTerminateObserver() selector:@selector(timeoutTimer:) userInfo:nil repeats:NO] retain] ); @@ -782,16 +666,6 @@ @implementation ChromeWindowsTerminatedObserver - (void) appTerminated:(NSNotification *)note { - // Not Chrome? Not interested. - if ( ![[[note userInfo] objectForKey:@"NSApplicationBundleIdentifier"] isEqualToString:appId] ) { - return; - } - - // Not LiveBrowser instance? Not interested. - if ( ![[[note userInfo] objectForKey:@"NSApplicationProcessIdentifier"] isEqualToNumber:[NSNumber numberWithInt:LiveBrowserMgrMac::GetInstance()->GetLiveBrowserPid()]] ) { - return; - } - LiveBrowserMgrMac::GetInstance()->CheckForChromeRunning(); } @@ -1262,184 +1136,3 @@ void DragWindow(CefRefPtr browser) [win displayIfNeeded]; } } - -int32 GetArgvFromProcessID(int pid, NSString **argv); -NSRunningApplication* GetLiveBrowserApp(NSString *bundleId, int debugPort) -{ - - NSArray* appList = [NSRunningApplication runningApplicationsWithBundleIdentifier: bundleId]; - - // Search list of running apps with bundleId + debug port - for (NSRunningApplication* currApp in appList) { - - int PID = [currApp processIdentifier]; - NSString* args = nil; - - // Check for process arguments - if (GetArgvFromProcessID(PID, &args) != NO_ERROR) { - continue; - } - - // Check debug port (e.g. --remote-debugging-port=9222) - if ([args rangeOfString:debugPortCommandlineArguments].location != NSNotFound) { - return currApp; - } - } - return nil; -} - -// Extracted & Modified from https://gist.github.com/nonowarn/770696 -int32 GetArgvFromProcessID(int pid, NSString **argv) -{ - int mib[3], argmax, nargs, c = 0; - size_t size; - char *procargs, *sp, *np, *cp; - int show_args = 1; - - mib[0] = CTL_KERN; - mib[1] = KERN_ARGMAX; - - size = sizeof(argmax); - if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) { - goto ERROR_A; - } - - /* Allocate space for the arguments. */ - procargs = (char *)malloc(argmax); - if (procargs == NULL) { - goto ERROR_A; - } - - - /* - * Make a sysctl() call to get the raw argument space of the process. - * The layout is documented in start.s, which is part of the Csu - * project. In summary, it looks like: - * - * /---------------\ 0x00000000 - * : : - * : : - * |---------------| - * | argc | - * |---------------| - * | arg[0] | - * |---------------| - * : : - * : : - * |---------------| - * | arg[argc - 1] | - * |---------------| - * | 0 | - * |---------------| - * | env[0] | - * |---------------| - * : : - * : : - * |---------------| - * | env[n] | - * |---------------| - * | 0 | - * |---------------| <-- Beginning of data returned by sysctl() is here. - * | argc | - * |---------------| - * | exec_path | - * |:::::::::::::::| - * | | - * | String area. | - * | | - * |---------------| <-- Top of stack. - * : : - * : : - * \---------------/ 0xffffffff - */ - mib[0] = CTL_KERN; - mib[1] = KERN_PROCARGS2; - mib[2] = pid; - - size = (size_t)argmax; - if (sysctl(mib, 3, procargs, &size, NULL, 0) == -1) { - goto ERROR_B; - } - - memcpy(&nargs, procargs, sizeof(nargs)); - cp = procargs + sizeof(nargs); - - /* Skip the saved exec_path. */ - for (; cp < &procargs[size]; cp++) { - if (*cp == '\0') { - /* End of exec_path reached. */ - break; - } - } - if (cp == &procargs[size]) { - goto ERROR_B; - } - - /* Skip trailing '\0' characters. */ - for (; cp < &procargs[size]; cp++) { - if (*cp != '\0') { - /* Beginning of first argument reached. */ - break; - } - } - if (cp == &procargs[size]) { - goto ERROR_B; - } - /* Save where the argv[0] string starts. */ - sp = cp; - - /* - * Iterate through the '\0'-terminated strings and convert '\0' to ' ' - * until a string is found that has a '=' character in it (or there are - * no more strings in procargs). There is no way to deterministically - * know where the command arguments end and the environment strings - * start, which is why the '=' character is searched for as a heuristic. - */ - for (np = NULL; c < nargs && cp < &procargs[size]; cp++) { - if (*cp == '\0') { - c++; - if (np != NULL) { - /* Convert previous '\0'. */ - *np = ' '; - } else { - /* *argv0len = cp - sp; */ - } - /* Note location of current '\0'. */ - np = cp; - - if (!show_args) { - /* - * Don't convert '\0' characters to ' '. - * However, we needed to know that the - * command name was terminated, which we - * now know. - */ - break; - } - } - } - - /* - * sp points to the beginning of the arguments/environment string, and - * np should point to the '\0' terminator for the string. - */ - if (np == NULL || np == sp) { - /* Empty or unterminated string. */ - goto ERROR_B; - } - - /* Make a copy of the string. */ - //printf("From function: %s\n", sp); - - /* Clean up. */ - free(procargs); - - *argv = [NSString stringWithCString:sp encoding:NSUTF8StringEncoding]; - return NO_ERROR; - -ERROR_B: - free(procargs); -ERROR_A: - //fprintf(stderr, "Sorry, failed\n"); - return ERR_UNKNOWN; -} \ No newline at end of file diff --git a/appshell/appshell_extensions_platform.h b/appshell/appshell_extensions_platform.h index 9d6faf0ff..5603ca6f5 100644 --- a/appshell/appshell_extensions_platform.h +++ b/appshell/appshell_extensions_platform.h @@ -44,7 +44,6 @@ static const int ERR_NOT_FILE = 8; static const int ERR_NOT_DIRECTORY = 9; static const int ERR_FILE_EXISTS = 10; static const int ERR_BROWSER_NOT_INSTALLED = 11; -static const int ERR_PID_NOT_FOUND = -9999; // negative int to avoid confusion with real PIDs #if defined(OS_WIN) typedef std::wstring ExtensionString;