Skip to content

Commit

Permalink
More or less working Skydrive authentication.
Browse files Browse the repository at this point in the history
  • Loading branch information
hatstand committed Dec 12, 2012
1 parent 8eea98b commit c4db401
Show file tree
Hide file tree
Showing 12 changed files with 141 additions and 11 deletions.
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand Down
1 change: 1 addition & 0 deletions data/data.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Binary file added data/providers/skydrive.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion src/internet/googledriveclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
6 changes: 6 additions & 0 deletions src/internet/internetmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
26 changes: 19 additions & 7 deletions src/internet/oauthenticator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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 {
Expand Down
14 changes: 11 additions & 3 deletions src/internet/oauthenticator.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);

Expand All @@ -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
61 changes: 61 additions & 0 deletions src/internet/skydriveservice.cpp
Original file line number Diff line number Diff line change
@@ -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());
}
26 changes: 26 additions & 0 deletions src/internet/skydriveservice.h
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions src/ui/settingsdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class SettingsDialog : public QDialog {
Page_GoogleDrive,
Page_UbuntuOne,
Page_Dropbox,
Page_Skydrive,
};

enum Role {
Expand Down

0 comments on commit c4db401

Please sign in to comment.