summaryrefslogtreecommitdiff
path: root/indra/llplugin
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llplugin')
-rw-r--r--indra/llplugin/llplugincookiestore.cpp36
-rw-r--r--indra/llplugin/slplugin/CMakeLists.txt20
-rw-r--r--indra/llplugin/slplugin/slplugin.cpp94
-rw-r--r--indra/llplugin/slplugin/slplugin_info.plist4
-rw-r--r--indra/llplugin/tests/llplugincookiestore_test.cpp2
5 files changed, 133 insertions, 23 deletions
diff --git a/indra/llplugin/llplugincookiestore.cpp b/indra/llplugin/llplugincookiestore.cpp
index 85b1e70d78..da770c5f2e 100644
--- a/indra/llplugin/llplugincookiestore.cpp
+++ b/indra/llplugin/llplugincookiestore.cpp
@@ -99,7 +99,7 @@ bool LLPluginCookieStore::Cookie::parse(const std::string &host)
std::string::size_type cookie_end = mCookie.size();
std::string::size_type field_start = 0;
- lldebugs << "parsing cookie: " << mCookie << llendl;
+ LL_DEBUGS("CookieStoreParse") << "parsing cookie: " << mCookie << LL_ENDL;
while(field_start < cookie_end)
{
// Finding the start of the next field requires honoring special quoting rules
@@ -167,10 +167,10 @@ bool LLPluginCookieStore::Cookie::parse(const std::string &host)
++value_end;
}
- lldebugs
+ LL_DEBUGS("CookieStoreParse")
<< " field name: \"" << mCookie.substr(name_start, name_end - name_start)
<< "\", value: \"" << mCookie.substr(value_start, value_end - value_start) << "\""
- << llendl;
+ << LL_ENDL;
// See whether this field is one we know
if(first_field)
@@ -195,13 +195,13 @@ bool LLPluginCookieStore::Cookie::parse(const std::string &host)
#if 1
time_t date = curl_getdate(date_string.c_str(), NULL );
mDate.secondsSinceEpoch((F64)date);
- lldebugs << " expire date parsed to: " << mDate.asRFC1123() << llendl;
+ LL_DEBUGS("CookieStoreParse") << " expire date parsed to: " << mDate.asRFC1123() << LL_ENDL;
#else
// This doesn't work (rfc1123-format dates cause it to fail)
if(!mDate.fromString(date_string))
{
// Date failed to parse.
- llwarns << "failed to parse cookie's expire date: " << date << llendl;
+ LL_WARNS("CookieStoreParse") << "failed to parse cookie's expire date: " << date << LL_ENDL;
return false;
}
#endif
@@ -232,9 +232,14 @@ bool LLPluginCookieStore::Cookie::parse(const std::string &host)
{
// We don't care about the value of this field (yet)
}
+ else if(matchName(name_start, name_end, "httponly"))
+ {
+ // We don't care about the value of this field (yet)
+ }
else
{
// An unknown field is a parse failure
+ LL_WARNS("CookieStoreParse") << "unexpected field name: " << mCookie.substr(name_start, name_end - name_start) << LL_ENDL;
return false;
}
@@ -270,7 +275,7 @@ bool LLPluginCookieStore::Cookie::parse(const std::string &host)
mCookie += host;
mDomainEnd = mCookie.size();
- lldebugs << "added domain (" << mDomainStart << " to " << mDomainEnd << "), new cookie is: " << mCookie << llendl;
+ LL_DEBUGS("CookieStoreParse") << "added domain (" << mDomainStart << " to " << mDomainEnd << "), new cookie is: " << mCookie << LL_ENDL;
}
// If the cookie doesn't have a path, add "/".
@@ -288,7 +293,7 @@ bool LLPluginCookieStore::Cookie::parse(const std::string &host)
mCookie += "/";
mPathEnd = mCookie.size();
- lldebugs << "added path (" << mPathStart << " to " << mPathEnd << "), new cookie is: " << mCookie << llendl;
+ LL_DEBUGS("CookieStoreParse") << "added path (" << mPathStart << " to " << mPathEnd << "), new cookie is: " << mCookie << LL_ENDL;
}
@@ -566,7 +571,7 @@ void LLPluginCookieStore::setOneCookie(const std::string &s, std::string::size_t
Cookie *cookie = Cookie::createFromString(s, cookie_start, cookie_end, host);
if(cookie)
{
- lldebugs << "setting cookie: " << cookie->getCookie() << llendl;
+ LL_DEBUGS("CookieStoreUpdate") << "setting cookie: " << cookie->getCookie() << LL_ENDL;
// Create a key for this cookie
std::string key = cookie->getKey();
@@ -579,7 +584,7 @@ void LLPluginCookieStore::setOneCookie(const std::string &s, std::string::size_t
{
// If we're marking cookies as changed, we should keep it anyway since we'll need to send it out with deltas.
cookie->setDead(true);
- lldebugs << " marking dead" << llendl;
+ LL_DEBUGS("CookieStoreUpdate") << " marking dead" << LL_ENDL;
}
else
{
@@ -590,7 +595,7 @@ void LLPluginCookieStore::setOneCookie(const std::string &s, std::string::size_t
delete cookie;
cookie = NULL;
- lldebugs << " removing" << llendl;
+ LL_DEBUGS("CookieStoreUpdate") << " removing" << LL_ENDL;
}
}
@@ -607,7 +612,7 @@ void LLPluginCookieStore::setOneCookie(const std::string &s, std::string::size_t
delete cookie;
cookie = NULL;
- lldebugs << " unchanged" << llendl;
+ LL_DEBUGS("CookieStoreUpdate") << " unchanged" << LL_ENDL;
}
else
{
@@ -619,7 +624,7 @@ void LLPluginCookieStore::setOneCookie(const std::string &s, std::string::size_t
if(mark_changed)
mHasChangedCookies = true;
- lldebugs << " replacing" << llendl;
+ LL_DEBUGS("CookieStoreUpdate") << " replacing" << LL_ENDL;
}
}
else
@@ -631,10 +636,15 @@ void LLPluginCookieStore::setOneCookie(const std::string &s, std::string::size_t
if(mark_changed)
mHasChangedCookies = true;
- lldebugs << " adding" << llendl;
+ LL_DEBUGS("CookieStoreUpdate") << " adding" << LL_ENDL;
}
}
}
+ else
+ {
+ LL_WARNS("CookieStoreUpdate") << "failed to parse cookie: " << s.substr(cookie_start, cookie_end - cookie_start) << LL_ENDL;
+ }
+
}
void LLPluginCookieStore::clearCookies()
diff --git a/indra/llplugin/slplugin/CMakeLists.txt b/indra/llplugin/slplugin/CMakeLists.txt
index 4a7d670c23..c1536e85de 100644
--- a/indra/llplugin/slplugin/CMakeLists.txt
+++ b/indra/llplugin/slplugin/CMakeLists.txt
@@ -27,9 +27,15 @@ set(SLPlugin_SOURCE_FILES
add_executable(SLPlugin
WIN32
+ MACOSX_BUNDLE
${SLPlugin_SOURCE_FILES}
)
+set_target_properties(SLPlugin
+ PROPERTIES
+ MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/slplugin_info.plist
+ )
+
target_link_libraries(SLPlugin
${LLPLUGIN_LIBRARIES}
${LLMESSAGE_LIBRARIES}
@@ -44,12 +50,16 @@ add_dependencies(SLPlugin
)
if (DARWIN)
- # Mac version needs to link against carbon, and also needs an embedded plist (to set LSBackgroundOnly)
+ # Mac version needs to link against Carbon
target_link_libraries(SLPlugin ${CARBON_LIBRARY})
- set_target_properties(
- SLPlugin
- PROPERTIES
- LINK_FLAGS "-Wl,-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_SOURCE_DIR}/slplugin_info.plist"
+ # Make sure the app bundle has a Resources directory (it will get populated by viewer-manifest.py later)
+ add_custom_command(
+ TARGET SLPlugin POST_BUILD
+ COMMAND mkdir
+ ARGS
+ -p
+ ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/SLPlugin.app/Contents/Resources
)
endif (DARWIN)
+ll_deploy_sharedlibs_command(SLPlugin)
diff --git a/indra/llplugin/slplugin/slplugin.cpp b/indra/llplugin/slplugin/slplugin.cpp
index 77240ce546..c18e2375f9 100644
--- a/indra/llplugin/slplugin/slplugin.cpp
+++ b/indra/llplugin/slplugin/slplugin.cpp
@@ -51,7 +51,7 @@
#endif
/*
- On Mac OS, since we call WaitNextEvent, this process will show up in the dock unless we set the LSBackgroundOnly flag in the Info.plist.
+ On Mac OS, since we call WaitNextEvent, this process will show up in the dock unless we set the LSBackgroundOnly or LSUIElement flag in the Info.plist.
Normally non-bundled binaries don't have an info.plist file, but it's possible to embed one in the binary by adding this to the linker flags:
@@ -60,7 +60,8 @@
which means adding this to the gcc flags:
-Wl,-sectcreate,__TEXT,__info_plist,/path/to/slplugin_info.plist
-
+
+ Now that SLPlugin is a bundled app on the Mac, this is no longer necessary (it can just use a regular Info.plist file), but I'm leaving this comment in for posterity.
*/
#if LL_DARWIN || LL_LINUX
@@ -239,6 +240,21 @@ int main(int argc, char **argv)
checkExceptionHandler();
#endif
+#if LL_DARWIN
+ // If the plugin opens a new window (such as the Flash plugin's fullscreen player), we may need to bring this plugin process to the foreground.
+ // Use this to track the current frontmost window and bring this process to the front if it changes.
+ WindowRef front_window = NULL;
+ WindowGroupRef layer_group = NULL;
+ int window_hack_state = 0;
+ CreateWindowGroup(kWindowGroupAttrFixedLevel, &layer_group);
+ if(layer_group)
+ {
+ // Start out with a window layer that's way out in front (fixes the problem with the menubar not getting hidden on first switch to fullscreen youtube)
+ SetWindowGroupName(layer_group, CFSTR("SLPlugin Layer"));
+ SetWindowGroupLevel(layer_group, kCGOverlayWindowLevel);
+ }
+#endif
+
while(!plugin->isDone())
{
timer.reset();
@@ -248,6 +264,80 @@ int main(int argc, char **argv)
// Some plugins (webkit at least) will want an event loop. This qualifies.
EventRecord evt;
WaitNextEvent(0, &evt, 0, NULL);
+
+ // Check for a change in this process's frontmost window.
+ if(FrontWindow() != front_window)
+ {
+ ProcessSerialNumber self = { 0, kCurrentProcess };
+ ProcessSerialNumber parent = { 0, kNoProcess };
+ ProcessSerialNumber front = { 0, kNoProcess };
+ Boolean this_is_front_process = false;
+ Boolean parent_is_front_process = false;
+ {
+ // Get this process's parent
+ ProcessInfoRec info;
+ info.processInfoLength = sizeof(ProcessInfoRec);
+ info.processName = NULL;
+ info.processAppSpec = NULL;
+ if(GetProcessInformation( &self, &info ) == noErr)
+ {
+ parent = info.processLauncher;
+ }
+
+ // and figure out whether this process or its parent are currently frontmost
+ if(GetFrontProcess(&front) == noErr)
+ {
+ (void) SameProcess(&self, &front, &this_is_front_process);
+ (void) SameProcess(&parent, &front, &parent_is_front_process);
+ }
+ }
+
+ if((FrontWindow() != NULL) && (front_window == NULL))
+ {
+ // Opening the first window
+
+ if(window_hack_state == 0)
+ {
+ // Next time through the event loop, lower the window group layer
+ window_hack_state = 1;
+ }
+
+ if(layer_group)
+ {
+ SetWindowGroup(FrontWindow(), layer_group);
+ }
+
+ if(parent_is_front_process)
+ {
+ // Bring this process's windows to the front.
+ (void) SetFrontProcess( &self );
+ }
+
+ ActivateWindow(FrontWindow(), true);
+ }
+ else if((FrontWindow() == NULL) && (front_window != NULL))
+ {
+ // Closing the last window
+
+ if(this_is_front_process)
+ {
+ // Try to bring this process's parent to the front
+ (void) SetFrontProcess(&parent);
+ }
+ }
+ else if(window_hack_state == 1)
+ {
+ if(layer_group)
+ {
+ // Set the window group level back to something less extreme
+ SetWindowGroupLevel(layer_group, kCGNormalWindowLevel);
+ }
+ window_hack_state = 2;
+ }
+
+ front_window = FrontWindow();
+
+ }
}
#endif
F64 elapsed = timer.getElapsedTimeF64();
diff --git a/indra/llplugin/slplugin/slplugin_info.plist b/indra/llplugin/slplugin/slplugin_info.plist
index b1daf87424..c4597380e0 100644
--- a/indra/llplugin/slplugin/slplugin_info.plist
+++ b/indra/llplugin/slplugin/slplugin_info.plist
@@ -6,7 +6,7 @@
<string>English</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
- <key>LSBackgroundOnly</key>
- <true/>
+ <key>LSUIElement</key>
+ <string>1</string>
</dict>
</plist>
diff --git a/indra/llplugin/tests/llplugincookiestore_test.cpp b/indra/llplugin/tests/llplugincookiestore_test.cpp
index 020d9c1977..c903464c64 100644
--- a/indra/llplugin/tests/llplugincookiestore_test.cpp
+++ b/indra/llplugin/tests/llplugincookiestore_test.cpp
@@ -127,7 +127,7 @@ namespace tut
// Valid, distinct cookies:
std::string cookie01 = "cookieA=value; domain=example.com; path=/";
- std::string cookie02 = "cookieB=value; domain=example.com; path=/"; // different name
+ std::string cookie02 = "cookieB=value; Domain=example.com; Path=/; Max-Age=10; Secure; Version=1; Comment=foo!; HTTPOnly"; // cookie with every supported field, in different cases.
std::string cookie03 = "cookieA=value; domain=foo.example.com; path=/"; // different domain
std::string cookie04 = "cookieA=value; domain=example.com; path=/bar/"; // different path
std::string cookie05 = "cookieC; domain=example.com; path=/"; // empty value