Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit 92e96e8

Browse files
[[ Bug 19909 ]] Add emscripten deploy library.
An internal command has been added to the Mac engine to return a list of all the installed web browsers. We get a similar list on Windows by querying the registry. For Linux we check a static list of browsers to see what's installed. The list of browsers is used as deploy targets for running HTML 5 standalones. The deploy library creates an instance of a local HTTP server using the HTTPd library, builds the standalone then launches the chosen browser, pointing it to the appropriate localhost path.
1 parent d977991 commit 92e96e8

File tree

5 files changed

+353
-0
lines changed

5 files changed

+353
-0
lines changed

engine/src/dsklnx.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2221,3 +2221,13 @@ MCSystemInterface *MCDesktopCreateLinuxSystem()
22212221
{
22222222
return new MCLinuxDesktop;
22232223
}
2224+
2225+
////////////////////////////////////////////////////////////////////////////////
2226+
2227+
bool MCS_get_browsers(MCStringRef &r_browsers)
2228+
{
2229+
r_browsers = nullptr;
2230+
return true;
2231+
}
2232+
2233+
////////////////////////////////////////////////////////////////////////////////

engine/src/dskmac.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5890,3 +5890,83 @@ static void MCS_startprocess_unix(MCNameRef name, MCStringRef doc, Open_mode mod
58905890
delete t_doc;
58915891

58925892
}
5893+
5894+
////////////////////////////////////////////////////////////////////////////////
5895+
5896+
bool MCS_get_browsers(MCStringRef &r_browsers)
5897+
{
5898+
bool t_success = true;
5899+
5900+
MCAutoListRef t_browser_list;
5901+
if (t_success)
5902+
t_success = MCListCreateMutable('\n', &t_browser_list);
5903+
5904+
CFURLRef t_url = nullptr;
5905+
if (t_success)
5906+
{
5907+
t_url = CFURLCreateWithString(nullptr, CFSTR("http://localhost"), nullptr);
5908+
t_success = t_url != nullptr;
5909+
}
5910+
5911+
CFArrayRef t_browsers = nullptr;
5912+
if (t_success)
5913+
t_browsers = LSCopyApplicationURLsForURL(t_url, kLSRolesAll);
5914+
5915+
if (t_success && t_browsers != nullptr)
5916+
{
5917+
for (CFIndex i = 0; t_success && i < CFArrayGetCount(t_browsers); ++i)
5918+
{
5919+
CFURLRef t_browser_url = (CFURLRef)CFArrayGetValueAtIndex(t_browsers, i);
5920+
5921+
CFStringRef t_browser_path = nullptr;
5922+
if (t_success)
5923+
{
5924+
t_browser_path = CFURLCopyFileSystemPath(t_browser_url, kCFURLPOSIXPathStyle);
5925+
t_success = t_browser_path != nullptr;
5926+
}
5927+
5928+
CFBundleRef t_browser_bundle = CFBundleCreate(nullptr, t_browser_url);
5929+
if (t_success)
5930+
{
5931+
t_browser_bundle = CFBundleCreate(nullptr, t_browser_url);
5932+
t_success = t_browser_bundle != nullptr;
5933+
}
5934+
5935+
CFStringRef t_browser_title = nullptr;
5936+
if (t_success)
5937+
{
5938+
5939+
CFStringRef t_name = (CFStringRef)CFBundleGetValueForInfoDictionaryKey(t_browser_bundle, kCFBundleNameKey);
5940+
CFStringRef t_version = (CFStringRef)CFBundleGetValueForInfoDictionaryKey(t_browser_bundle, kCFBundleVersionKey);
5941+
t_browser_title = CFStringCreateWithFormat(nullptr, nullptr, CFSTR("%@ (%@),%@"), t_name, t_version, t_browser_path);
5942+
t_success = t_browser_title != nullptr;
5943+
}
5944+
5945+
MCAutoStringRef t_browser_string;
5946+
if (t_success)
5947+
t_success = MCStringCreateWithCFString(t_browser_title, &t_browser_string);
5948+
5949+
if (t_success)
5950+
t_success = MCListAppend(*t_browser_list, *t_browser_string);
5951+
5952+
if (t_browser_path != nullptr)
5953+
CFRelease(t_browser_path);
5954+
if (t_browser_bundle != nullptr)
5955+
CFRelease(t_browser_bundle);
5956+
if (t_browser_title != nullptr)
5957+
CFRelease(t_browser_title);
5958+
}
5959+
}
5960+
5961+
if (t_success)
5962+
t_success = MCListCopyAsString(*t_browser_list, r_browsers);
5963+
5964+
if (t_browsers != nullptr)
5965+
CFRelease(t_browsers);
5966+
if (t_url != nullptr)
5967+
CFRelease(t_url);
5968+
5969+
return t_success;
5970+
}
5971+
5972+
////////////////////////////////////////////////////////////////////////////////

engine/src/dskw32.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3870,3 +3870,11 @@ uint2 MCS_charsettolangid(uint1 charset)
38703870
}
38713871

38723872
////////////////////////////////////////////////////////////////////////////////
3873+
3874+
bool MCS_get_browsers(MCStringRef &r_browsers)
3875+
{
3876+
r_browsers = nullptr;
3877+
return true;
3878+
}
3879+
3880+
////////////////////////////////////////////////////////////////////////////////

engine/src/internal_development.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,28 @@ class MCInternalObjectUnListen: public MCStatement
783783

784784
////////////////////////////////////////////////////////////////////////////////
785785

786+
extern bool MCS_get_browsers(MCStringRef &r_browsers);
787+
788+
class MCInternalListBrowsers: public MCStatement
789+
{
790+
public:
791+
Parse_stat parse(MCScriptPoint& sp)
792+
{
793+
return PS_NORMAL;
794+
}
795+
796+
void exec_ctxt(MCExecContext &ctxt)
797+
{
798+
MCAutoStringRef t_browsers;
799+
if (MCS_get_browsers(&t_browsers))
800+
ctxt.SetTheResultToValue(*t_browsers);
801+
else
802+
ctxt.SetTheResultToEmpty();
803+
}
804+
};
805+
806+
////////////////////////////////////////////////////////////////////////////////
807+
786808
template<class T> inline MCStatement *class_factory(void)
787809
{
788810
return new T;
@@ -816,6 +838,8 @@ MCInternalVerbInfo MCinternalverbs[] =
816838
{ "syntax", "recognize", class_factory<MCIdeSyntaxRecognize> },
817839
{ "syntax", "compile", class_factory<MCIdeSyntaxCompile> },
818840
{ "filter", "controls", class_factory<MCIdeFilterControls> },
841+
{ "list", "browsers", class_factory<MCInternalListBrowsers> },
842+
819843
{ nil, nil, nil }
820844
};
821845

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
script "revdeploylibraryemscripten"
2+
/* Copyright (C) 2017 LiveCode Ltd.
3+
4+
This file is part of LiveCode.
5+
6+
LiveCode is free software; you can redistribute it and/or modify it under
7+
the terms of the GNU General Public License v3 as published by the Free
8+
Software Foundation.
9+
10+
LiveCode is distributed in the hope that it will be useful, but WITHOUT ANY
11+
WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
17+
18+
constant kLinuxBrowserList = "Firefox=firefox/firefox,Firefox Beta=firefox_beta/firefox,Firefox Aurora=firefox_aurora/firefox,Firefox Nightly=firefox_nightly/firefox,Chrome Stable=google-chrome-stable/google-chrome-stable,Chrome=google-chrome/google-chrome"
19+
20+
local sBrowsers
21+
local sServerPort
22+
local sHTTPFileSpace
23+
24+
command deployInitialize
25+
local tBrowserList
26+
put __deployGetBrowserList() into tBrowserList
27+
split tBrowserList by return and comma
28+
put tBrowserList into sBrowsers
29+
30+
put the temporary folder & slash & "livecode-emscripten-builds" into sHTTPFileSpace
31+
if not (there is a folder sHTTPFileSpace) then
32+
create folder sHTTPFileSpace
33+
end if
34+
end deployInitialize
35+
36+
function deployIsAvailable
37+
get deployListTargets()
38+
return it is not empty
39+
end deployIsAvailable
40+
41+
function deployListTargets
42+
local tTargets
43+
put the keys of sBrowsers into tTargets
44+
sort tTargets
45+
if tTargets is not empty then
46+
put return before tTargets
47+
end if
48+
put "Default Browser" before tTargets
49+
return tTargets
50+
end deployListTargets
51+
52+
-- Create a local HTTP server using the HTTPd library,
53+
-- build the HTML 5 standalone then launch the local URL
54+
-- for the standalone in the chosen browser.
55+
--
56+
command deployDo pTargetStack, pBrowser
57+
local tError
58+
put empty into tError
59+
60+
if tError is empty then
61+
revStandaloneProgress "Configuring HTTP server..."
62+
63+
if sServerPort is not empty and sServerPort is not among the lines of the openSockets then
64+
httpdStop sServerPort
65+
put empty into sServerPort
66+
end if
67+
68+
if sServerPort is empty then
69+
httpdStart "deployEmscriptenNewHTTPRequest", 0
70+
if the result is not empty or it is not an integer then
71+
put "Could not start HTTP server" && the result && it into tError
72+
else
73+
put it into sServerPort
74+
end if
75+
end if
76+
end if
77+
78+
local tBuildFolder, tStandalonePath
79+
if tError is empty then
80+
revStandaloneProgress "Building standalone..."
81+
82+
local tSettings
83+
put revSBGetSettings(pTargetStack, true) into tSettings
84+
revSearchForInclusions pTargetStack, tSettings
85+
86+
put sHTTPFileSpace & slash & tSettings["name"] into tBuildFolder
87+
if there is a folder tBuildFolder then
88+
revDeleteFolder tBuildFolder
89+
end if
90+
create folder tBuildFolder
91+
92+
put urlencode(tSettings["name"]) & slash & urlencode(tSettings["name"]) & ".html" into tStandalonePath
93+
94+
try
95+
dispatch "revSaveAsEmscriptenStandalone" to stack "revsaveasemscriptenstandalone" with \
96+
pTargetStack, tBuildFolder, tSettings
97+
catch tException
98+
put "Unable to build app for testing:" && tException into tError
99+
end try
100+
end if
101+
102+
if tError is empty then
103+
revStandaloneProgress "Launching URL..."
104+
105+
__deployLaunchURLInBrowser "http://localhost:" & sServerPort & slash & tStandalonePath, sBrowsers[pBrowser]
106+
if the result is not empty then
107+
put "Could not open URL" && the result into tError
108+
end if
109+
end if
110+
111+
if tError is not empty and there is a folder tBuildFolder then
112+
revDeleteFolder tBuildFolder
113+
end if
114+
115+
if "revStandaloneProgress" is among the lines of the openStacks then
116+
close stack "revStandaloneProgress"
117+
end if
118+
119+
return tError
120+
end deployDo
121+
122+
////////////////////////////////////////////////////////////////////////////////
123+
124+
private function __wrapInQuotes pString
125+
return quote & pString & quote
126+
end __wrapInQuotes
127+
128+
-- Returns a return delimited list of the form <browser>,<path to exe>
129+
-- Use an internal command on OSX, the registery in Windows and a static list on Linux.
130+
-- Not implemented on other platforms - we just use the default browser here.
131+
--
132+
private function __deployGetBrowserList
133+
local tBrowserList
134+
135+
switch the platform
136+
case "MacOS"
137+
_internal list browsers
138+
put the result into tBrowserList
139+
break
140+
141+
case "Win32"
142+
-- According to https://msdn.microsoft.com/en-us/library/dd203067(VS.85).aspx
143+
-- browsers should register in the registry at HKEY_LOCAL_MACHINE\SOFTWARE\Clients\StartMenuInternet
144+
--
145+
local tBrowsers
146+
put listRegistry("HKEY_LOCAL_MACHINE\SOFTWARE\Clients\StartMenuInternet") into tBrowsers
147+
repeat for each line tBrowser in tBrowsers
148+
if tBrowserList is not empty then
149+
put return after tBrowserList
150+
end if
151+
put queryRegistry("HKEY_LOCAL_MACHINE\SOFTWARE\Clients\StartMenuInternet\" & tBrowser & backslash) & comma & \
152+
queryRegistry("HKEY_LOCAL_MACHINE\SOFTWARE\Clients\StartMenuInternet\" & tBrowser & "\shell\open\command\") after tBrowserList
153+
end repeat
154+
replace quote with empty in tBrowserList
155+
break
156+
157+
case "Linux"
158+
-- For linux, we have a list of known browsers.
159+
-- Check to see if the exe is in the path or installed in the user's home dir.
160+
--
161+
local tBrowserArray
162+
put kLinuxBrowserList into tBrowserArray
163+
split tBrowserArray by comma and "="
164+
165+
set the itemDel to slash
166+
repeat for each key tBrowser in tBrowserArray
167+
get shell("which" && item 1 of tBrowserArray[tBrowser])
168+
if it is not empty then
169+
put it into tBrowserList[tBrowser]
170+
else
171+
local tUserBrowserPath
172+
put $HOME & slash & tBrowserArray[tBrowser] into tUserBrowserPath
173+
if there is a file tUserBrowserPath then
174+
put tUserBrowserPath into tBrowserList[tBrowser]
175+
end if
176+
end if
177+
end repeat
178+
set the itemDel to comma
179+
180+
combine tBrowserList with return and comma
181+
break
182+
183+
default
184+
put empty into tBrowserList
185+
break
186+
end switch
187+
188+
return tBrowserList
189+
end __deployGetBrowserList
190+
191+
private command __deployLaunchURLInBrowser pURL, pBrowser
192+
if pBrowser is empty then
193+
launch URL pURL
194+
return the result
195+
else
196+
switch the platform
197+
case "MacOS"
198+
return shell("open -a" && __wrapInQuotes(pBrowser) && __wrapInQuotes(pURL))
199+
200+
case "Win32"
201+
local tHideConsoleWindows
202+
put the hideConsoleWindows into tHideConsoleWindows
203+
set the hideConsoleWindows to true
204+
get shell(__wrapInQuotes(pBrowser) && __wrapInQuotes(pURL))
205+
set the hideConsoleWindows to tHideConsoleWindows
206+
return it
207+
208+
case "Linux"
209+
return shell(__wrapInQuotes(pBrowser) && __wrapInQuotes(pURL))
210+
211+
default
212+
launch URL pURL
213+
return the result
214+
end switch
215+
end if
216+
end __deployLaunchURLInBrowser
217+
218+
-- Callback from the HTTP deamon.
219+
-- In this case we just want to serve the requested file
220+
-- if it exists in the temp file space.
221+
--
222+
on deployEmscriptenNewHTTPRequest pSocketID, pRequest
223+
local tPath
224+
put sHTTPFileSpace & slash & pRequest["resource"] into tPath
225+
226+
if there is a file tPath then
227+
httpdResponse pSocketID, 200, URL ("binfile:" & tPath)
228+
else
229+
httpdResponse pSocketID, 404
230+
end if
231+
end deployEmscriptenNewHTTPRequest

0 commit comments

Comments
 (0)