summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorthestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-22 18:42:12 +0000
committerthestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-22 18:42:12 +0000
commit500bdbe6de1a8dd68d84ef6a3fde61be705029b2 (patch)
treedd32694203a3fdc0f229e9972329be7a0340e195
parent817e1dd8ae6ed6be46c408a7c7ee579888f55e67 (diff)
downloadchromium_src-500bdbe6de1a8dd68d84ef6a3fde61be705029b2.zip
chromium_src-500bdbe6de1a8dd68d84ef6a3fde61be705029b2.tar.gz
chromium_src-500bdbe6de1a8dd68d84ef6a3fde61be705029b2.tar.bz2
Linux: Dynamically load libgnutls.so in the cloud printing CUPS code.
BUG=46954 TEST=chrome binary built on Hardy no longer explictily depend on libgnutls.so.13. Review URL: http://codereview.chromium.org/2823018 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@50487 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/chrome.gyp1
-rw-r--r--chrome/service/cloud_print/print_system.h2
-rw-r--r--chrome/service/cloud_print/print_system_cups.cc80
3 files changed, 57 insertions, 26 deletions
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index a486c7d..f55067f 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -1131,7 +1131,6 @@
'libraries': [
'-lcups',
'-lgcrypt',
- '-lgnutls',
],
},
'defines': [
diff --git a/chrome/service/cloud_print/print_system.h b/chrome/service/cloud_print/print_system.h
index 23f6f41..b7d0ce5 100644
--- a/chrome/service/cloud_print/print_system.h
+++ b/chrome/service/cloud_print/print_system.h
@@ -12,7 +12,6 @@
#include "base/file_path.h"
#include "base/ref_counted.h"
#include "base/values.h"
-#include "googleurl/src/gurl.h"
// This is the interface for platform-specific code for cloud print
namespace cloud_print {
@@ -169,4 +168,3 @@ typedef PrintSystem::PrinterWatcher::Delegate PrinterWatcherDelegate;
} // namespace cloud_print
#endif // CHROME_SERVICE_CLOUD_PRINT_PRINT_SYSTEM_H_
-
diff --git a/chrome/service/cloud_print/print_system_cups.cc b/chrome/service/cloud_print/print_system_cups.cc
index 2f32a5a..b624f40 100644
--- a/chrome/service/cloud_print/print_system_cups.cc
+++ b/chrome/service/cloud_print/print_system_cups.cc
@@ -5,56 +5,92 @@
#include "chrome/service/cloud_print/print_system.h"
#include <cups/cups.h>
-#include <list>
-#include <map>
-
-#include <gnutls/gnutls.h>
-#include <gcrypt.h>
+#include <dlfcn.h>
#include <errno.h>
+#include <gcrypt.h>
#include <pthread.h>
-#include "base/json/json_reader.h"
+#include <list>
+#include <map>
+
#include "base/file_path.h"
#include "base/file_util.h"
-#include "base/logging.h"
+#include "base/json/json_reader.h"
#include "base/lock.h"
+#include "base/logging.h"
#include "base/message_loop.h"
#include "base/rand_util.h"
#include "base/string_util.h"
#include "base/task.h"
#include "base/utf_string_conversions.h"
+#include "googleurl/src/gurl.h"
-namespace cloud_print {
-
-static const char kCUPSPrinterInfoOpt[] = "printer-info";
-static const char kCUPSPrinterStateOpt[] = "printer-state";
-static const wchar_t kCUPSPrintServerURL[] = L"print_server_url";
-
-// Default port for IPP print servers.
-static const int kDefaultIPPServerPort = 631;
+namespace {
// Init GCrypt library (needed for CUPS) using pthreads.
// I've hit a bug in CUPS library, when it crashed with: "ath.c:184:
// _gcry_ath_mutex_lock: Assertion `*lock == ((ath_mutex_t) 0)' failed."
// It happened whe multiple threads tried printing simultaneously.
-// Google search for 'gnutls thread safety' provided with following solution.
+// Google search for 'gnutls thread safety' provided with following solution
+// where we initialize gcrypt by initializing gnutls.
+//
+// Initially, we linked with -lgnutls and simply called gnutls_global_init(),
+// but this did not work well since we build one binary on Ubuntu Hardy and
+// expect it to run on many Linux distros. (See http://crbug.com/46954)
+// So instead we use dlopen() and dlsym() to dynamically load and call
+// gnutls_global_init().
GCRY_THREAD_OPTION_PTHREAD_IMPL;
+bool init_gnutls() {
+ const char* kGnuTlsFile = "libgnutls.so";
+ void* gnutls_lib = dlopen(kGnuTlsFile, RTLD_NOW);
+ if (!gnutls_lib) {
+ LOG(ERROR) << "Cannot load " << kGnuTlsFile;
+ return false;
+ }
+ const char* kGnuTlsInitFuncName = "gnutls_global_init";
+ int (*pgnutls_global_init)(void) = reinterpret_cast<int(*)()>(
+ dlsym(gnutls_lib, kGnuTlsInitFuncName));
+ if (!pgnutls_global_init) {
+ LOG(ERROR) << "Could not find " << kGnuTlsInitFuncName
+ << " in " << kGnuTlsFile;
+ return false;
+ }
+ return ((*pgnutls_global_init)() == 0);
+}
+
void init_gcrypt() {
+ // The gnutls_global_init() man page warns it's not thread safe. Locking this
+ // entire function just to be on the safe side.
+ static Lock init_gcrypt_lock;
+ AutoLock init_gcrypt_autolock(init_gcrypt_lock);
static bool gcrypt_initialized = false;
if (!gcrypt_initialized) {
gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
- gnutls_global_init();
- gcrypt_initialized = true;
+ gcrypt_initialized = init_gnutls();
+ if (!gcrypt_initialized) {
+ LOG(ERROR) << "Gcrypt initialization failed";
+ }
}
}
+} // namespace
+
+namespace cloud_print {
+
+static const char kCUPSPrinterInfoOpt[] = "printer-info";
+static const char kCUPSPrinterStateOpt[] = "printer-state";
+static const wchar_t kCUPSPrintServerURL[] = L"print_server_url";
+
+// Default port for IPP print servers.
+static const int kDefaultIPPServerPort = 631;
+
// Helper wrapper around http_t structure, with connection and cleanup
// functionality.
class HttpConnectionCUPS {
public:
- explicit HttpConnectionCUPS(const GURL& print_server_url) : http_(NULL) {
+ explicit HttpConnectionCUPS(const GURL& print_server_url) : http_(NULL) {
// If we have an empty url, use default print server.
if (print_server_url.is_empty())
return;
@@ -67,7 +103,7 @@ class HttpConnectionCUPS {
HTTP_ENCRYPT_NEVER);
if (http_ == NULL) {
LOG(ERROR) << "CP_CUPS: Failed connecting to print server: " <<
- print_server_url;
+ print_server_url;
}
}
@@ -462,7 +498,7 @@ FilePath PrintSystemCUPS::GetPPD(const char* name) {
// cupsGetPPD returns a filename stored in a static buffer in CUPS.
// Protect this code with lock.
static Lock ppd_lock;
- ppd_lock.Acquire();
+ AutoLock ppd_autolock(ppd_lock);
FilePath ppd_path;
const char* ppd_file_path = NULL;
if (print_server_url_.is_empty()) { // Use default (local) print server.
@@ -473,7 +509,6 @@ FilePath PrintSystemCUPS::GetPPD(const char* name) {
}
if (ppd_file_path)
ppd_path = FilePath(ppd_file_path);
- ppd_lock.Release();
return ppd_path;
}
@@ -500,4 +535,3 @@ int PrintSystemCUPS::GetJobs(cups_job_t** jobs, const char* name,
}
} // namespace cloud_print
-