More or less working Skydrive authentication.

This commit is contained in:
John Maguire 2012-12-12 18:34:15 +01:00
parent 8eea98ba66
commit c4db401597
12 changed files with 141 additions and 11 deletions

View File

@ -202,6 +202,11 @@ optional_component(DROPBOX ON "Dropbox support"
DEPENDS "Taglib 1.8" "TAGLIB_VERSION VERSION_GREATER 1.7.999"
)
optional_component(SKYDRIVE ON "Skydrive support"
DEPENDS "Google sparsehash" SPARSEHASH_INCLUDE_DIRS
DEPENDS "Taglib 1.8" "TAGLIB_VERSION VERSION_GREATER 1.7.999"
)
optional_component(AUDIOCD ON "Devices: Audio CD support"
DEPENDS "libcdio" CDIO_FOUND
)

View File

@ -291,6 +291,7 @@
<file>providers/podcast16.png</file>
<file>providers/podcast32.png</file>
<file>providers/rockradio.png</file>
<file>providers/skydrive.png</file>
<file>providers/skyfm.png</file>
<file>providers/somafm.png</file>
<file>providers/songkick.png</file>

BIN
data/providers/skydrive.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -1072,6 +1072,14 @@ optional_source(HAVE_DROPBOX
internet/dropboxsettingspage.ui
)
# Skydrive support
optional_source(HAVE_SKYDRIVE
SOURCES
internet/skydriveservice.cpp
HEADERS
internet/skydriveservice.h
)
# Hack to add Clementine to the Unity system tray whitelist
optional_source(LINUX
SOURCES core/ubuntuunityhack.cpp

View File

@ -36,6 +36,7 @@
#cmakedefine HAVE_LIBMTP
#cmakedefine HAVE_MOODBAR
#cmakedefine HAVE_QCA
#cmakedefine HAVE_SKYDRIVE
#cmakedefine HAVE_SPARKLE
#cmakedefine HAVE_SPOTIFY
#cmakedefine HAVE_SPOTIFY_DOWNLOADER

View File

@ -89,7 +89,8 @@ Client::Client(QObject* parent)
ConnectResponse* Client::Connect(const QString& refresh_token) {
ConnectResponse* ret = new ConnectResponse(this);
OAuthenticator* oauth = new OAuthenticator(kClientId, kClientSecret, this);
OAuthenticator* oauth = new OAuthenticator(
kClientId, kClientSecret, OAuthenticator::RedirectStyle::LOCALHOST, this);
if (refresh_token.isEmpty()) {
oauth->StartAuthorisation(

View File

@ -51,6 +51,9 @@
#ifdef HAVE_DROPBOX
#include "dropboxservice.h"
#endif
#ifdef HAVE_SKYDRIVE
#include "skydriveservice.h"
#endif
using smart_playlists::Generator;
using smart_playlists::GeneratorMimeData;
@ -97,6 +100,9 @@ InternetModel::InternetModel(Application* app, QObject* parent)
#ifdef HAVE_DROPBOX
AddService(new DropboxService(app, this));
#endif
#ifdef HAVE_SKYDRIVE
AddService(new SkydriveService(app, this));
#endif
}
void InternetModel::AddService(InternetService *service) {

View File

@ -13,10 +13,12 @@
OAuthenticator::OAuthenticator(
const QString& client_id,
const QString& client_secret,
RedirectStyle redirect,
QObject* parent)
: QObject(parent),
client_id_(client_id),
client_secret_(client_secret) {
client_secret_(client_secret),
redirect_style_(redirect) {
}
void OAuthenticator::StartAuthorisation(
@ -27,25 +29,35 @@ void OAuthenticator::StartAuthorisation(
LocalRedirectServer* server = new LocalRedirectServer(this);
server->Listen();
NewClosure(server, SIGNAL(Finished()),
this, SLOT(RedirectArrived(LocalRedirectServer*)), server);
QUrl url = QUrl(oauth_endpoint);
url.addQueryItem("response_type", "code");
url.addQueryItem("client_id", client_id_);
url.addQueryItem("redirect_uri", server->url().toString());
QUrl redirect_url;
if (redirect_style_ == RedirectStyle::REMOTE) {
const int port = server->url().port();
redirect_url = QUrl(
QString("http://data.clementine-player.org/skydrive?port=%1").arg(port));
} else {
redirect_url = server->url();
}
url.addQueryItem("redirect_uri", redirect_url.toString());
url.addQueryItem("scope", scope);
NewClosure(server, SIGNAL(Finished()),
this, SLOT(RedirectArrived(LocalRedirectServer*,QUrl)),
server, redirect_url);
QDesktopServices::openUrl(url);
}
void OAuthenticator::RedirectArrived(LocalRedirectServer* server) {
void OAuthenticator::RedirectArrived(
LocalRedirectServer* server, QUrl url) {
server->deleteLater();
QUrl request_url = server->request_url();
qLog(Debug) << Q_FUNC_INFO << request_url;
RequestAccessToken(
request_url.queryItemValue("code").toUtf8(),
server->url());
url);
}
QByteArray OAuthenticator::ParseHttpRequest(const QByteArray& request) const {

View File

@ -12,9 +12,18 @@ class QTcpSocket;
class OAuthenticator : public QObject {
Q_OBJECT
public:
enum class RedirectStyle {
// Redirect to localhost immediately.
LOCALHOST = 0,
// Redirect via data.clementine-player.org for when localhost is
// unsupported (eg. Skydrive).
REMOTE = 1,
};
OAuthenticator(
const QString& client_id,
const QString& client_secret,
RedirectStyle redirect,
QObject* parent = 0);
void StartAuthorisation(
const QString& oauth_endpoint,
@ -31,13 +40,12 @@ class OAuthenticator : public QObject {
const QString& refresh_token() const { return refresh_token_; }
const QDateTime& expiry_time() const { return expiry_time_; }
const QString& user_email() const { return user_email_; }
signals:
void Finished();
private slots:
void RedirectArrived(LocalRedirectServer* server);
void RedirectArrived(LocalRedirectServer* server, QUrl url);
void FetchAccessTokenFinished(QNetworkReply* reply);
void RefreshAccessTokenFinished(QNetworkReply* reply);
@ -51,11 +59,11 @@ class OAuthenticator : public QObject {
QString access_token_;
QString refresh_token_;
QDateTime expiry_time_;
QString user_email_;
const QString client_id_;
const QString client_secret_;
QUrl token_endpoint_;
RedirectStyle redirect_style_;
};
#endif

View File

@ -0,0 +1,61 @@
#include "skydriveservice.h"
#include "oauthenticator.h"
namespace {
static const char* kServiceName = "Skydrive";
static const char* kServiceId = "skydrive";
static const char* kSettingsGroup = "Skydrive";
static const char* kClientId = "00000000400E7C78";
static const char* kClientSecret = "B0KLZjEgC5SpW0KknrsBFwlaKmGThaAk";
static const char* kOAuthEndpoint =
"https://login.live.com/oauth20_authorize.srf";
static const char* kOAuthTokenEndpoint =
"https://login.live.com/oauth20_token.srf";
static const char* kOAuthScope = "wl.basic wl.skydrive wl.offline_access";
} // namespace
SkydriveService::SkydriveService(
Application* app,
InternetModel* parent)
: CloudFileService(
app, parent, kServiceName, kServiceId,
QIcon(":providers/skydrive.png"), SettingsDialog::Page_Skydrive) {
}
bool SkydriveService::has_credentials() const {
return true;
}
void SkydriveService::Connect() {
OAuthenticator* oauth = new OAuthenticator(
kClientId, kClientSecret, OAuthenticator::RedirectStyle::REMOTE, this);
QSettings s;
s.beginGroup(kSettingsGroup);
if (s.contains("refresh_token")) {
oauth->RefreshAuthorisation(
kOAuthTokenEndpoint, s.value("refresh_token").toString());
} else {
oauth->StartAuthorisation(
kOAuthEndpoint,
kOAuthTokenEndpoint,
kOAuthScope);
}
NewClosure(oauth, SIGNAL(Finished()),
this, SLOT(ConnectFinished(OAuthenticator*)), oauth);
}
void SkydriveService::ConnectFinished(OAuthenticator* oauth) {
qLog(Debug) << oauth->access_token()
<< oauth->refresh_token();
QSettings s;
s.beginGroup(kSettingsGroup);
s.setValue("refresh_token", oauth->refresh_token());
}

View File

@ -0,0 +1,26 @@
#ifndef SKYDRIVESERVICE_H
#define SKYDRIVESERVICE_H
#include "cloudfileservice.h"
class OAuthenticator;
class SkydriveService : public CloudFileService {
Q_OBJECT
public:
SkydriveService(
Application* app,
InternetModel* parent);
protected:
// CloudFileService
virtual bool has_credentials() const;
virtual void Connect();
private slots:
void ConnectFinished(OAuthenticator* oauth);
};
#endif // SKYDRIVESERVICE_H

View File

@ -79,6 +79,7 @@ public:
Page_GoogleDrive,
Page_UbuntuOne,
Page_Dropbox,
Page_Skydrive,
};
enum Role {