diff --git a/data/data.qrc b/data/data.qrc
index 164f9421e..edda37da4 100644
--- a/data/data.qrc
+++ b/data/data.qrc
@@ -294,6 +294,7 @@
providers/somafm.png
providers/songkick.png
providers/soundcloud.png
+ providers/ubuntuone.png
providers/wikipedia.png
sample.mood
schema/device-schema.sql
diff --git a/data/providers/podcast16.png b/data/providers/podcast16.png
old mode 100755
new mode 100644
diff --git a/data/providers/podcast32.png b/data/providers/podcast32.png
old mode 100755
new mode 100644
diff --git a/data/providers/ubuntuone.png b/data/providers/ubuntuone.png
new file mode 100644
index 000000000..4513269f8
Binary files /dev/null and b/data/providers/ubuntuone.png differ
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 78b2e11e4..14ac63fc9 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -192,6 +192,7 @@ set(SOURCES
internet/soundcloudservice.cpp
internet/ubuntuoneauthenticator.cpp
internet/ubuntuoneservice.cpp
+ internet/ubuntuonesettingspage.cpp
internet/ubuntuoneurlhandler.cpp
library/groupbydialog.cpp
@@ -469,6 +470,7 @@ set(HEADERS
internet/soundcloudservice.h
internet/ubuntuoneauthenticator.h
internet/ubuntuoneservice.h
+ internet/ubuntuonesettingspage.h
internet/ubuntuoneurlhandler.h
library/groupbydialog.h
@@ -645,6 +647,7 @@ set(UI
internet/magnatunesettingspage.ui
internet/searchboxwidget.ui
internet/spotifysettingspage.ui
+ internet/ubuntuonesettingspage.ui
library/groupbydialog.ui
library/libraryfilterwidget.ui
diff --git a/src/internet/googledrivesettingspage.h b/src/internet/googledrivesettingspage.h
index 77de3d08c..cbf39a417 100644
--- a/src/internet/googledrivesettingspage.h
+++ b/src/internet/googledrivesettingspage.h
@@ -1,16 +1,16 @@
/* This file is part of Clementine.
Copyright 2012, David Sansome
-
+
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with Clementine. If not, see .
*/
@@ -26,11 +26,9 @@
class GoogleDriveService;
class Ui_GoogleDriveSettingsPage;
-class QSortFilterProxyModel;
-
class GoogleDriveSettingsPage : public SettingsPage {
Q_OBJECT
-
+
public:
GoogleDriveSettingsPage(SettingsDialog* parent = 0);
~GoogleDriveSettingsPage();
diff --git a/src/internet/ubuntuoneauthenticator.cpp b/src/internet/ubuntuoneauthenticator.cpp
index 729a03828..6f0540d4c 100644
--- a/src/internet/ubuntuoneauthenticator.cpp
+++ b/src/internet/ubuntuoneauthenticator.cpp
@@ -1,18 +1,24 @@
#include "ubuntuoneauthenticator.h"
#include
+#include
#include
+#include
#include
#include "core/closure.h"
#include "core/logging.h"
#include "core/network.h"
+#include "core/timeconstants.h"
namespace {
static const char* kUbuntuOneEndpoint =
"https://login.ubuntu.com/api/1.0/authentications";
static const char* kTokenNameTemplate = "Ubuntu One @ %1 [%2]";
+static const char* kOAuthSSOFinishedEndpoint =
+ "https://one.ubuntu.com/oauth/sso-finished-so-get-tokens/";
+static const char* kOAuthHeaderPrefix = "OAuth realm=\"\", ";
}
UbuntuOneAuthenticator::UbuntuOneAuthenticator(QObject* parent)
@@ -66,5 +72,67 @@ void UbuntuOneAuthenticator::AuthorisationFinished(QNetworkReply* reply) {
token_ = auth_info["token"].toString();
token_secret_ = auth_info["token_secret"].toString();
+ CopySSOTokens();
+}
+
+QByteArray UbuntuOneAuthenticator::GenerateAuthorisationHeader(
+ const QString& consumer_key,
+ const QString& consumer_secret,
+ const QString& token,
+ const QString& token_secret) {
+ typedef QPair Param;
+ QString timestamp = QString::number(
+ QDateTime::currentMSecsSinceEpoch() / kMsecPerSec);
+ QList parameters;
+ parameters << Param("oauth_nonce", QString::number(qrand()))
+ << Param("oauth_timestamp", timestamp)
+ << Param("oauth_version", "1.0")
+ << Param("oauth_consumer_key", consumer_key)
+ << Param("oauth_token", token)
+ << Param("oauth_signature_method", "PLAINTEXT");
+ qSort(parameters.begin(), parameters.end());
+ QStringList encoded_params;
+ for (const Param& p : parameters) {
+ encoded_params << QString("%1=%2").arg(p.first, p.second);
+ }
+
+ QString signing_key =
+ consumer_secret + "&" + token_secret;
+ QByteArray signature = QUrl::toPercentEncoding(signing_key);
+
+ // Construct authorisation header
+ parameters << Param("oauth_signature", signature);
+ QStringList header_params;
+ for (const Param& p : parameters) {
+ header_params << QString("%1=\"%2\"").arg(p.first, p.second);
+ }
+ QString authorisation_header = header_params.join(", ");
+ authorisation_header.prepend(kOAuthHeaderPrefix);
+
+ return authorisation_header.toAscii();
+}
+
+QByteArray UbuntuOneAuthenticator::GenerateAuthorisationHeader() {
+ return GenerateAuthorisationHeader(
+ consumer_key_,
+ consumer_secret_,
+ token_,
+ token_secret_);
+}
+
+void UbuntuOneAuthenticator::CopySSOTokens() {
+ QUrl url(kOAuthSSOFinishedEndpoint);
+ QNetworkRequest request(url);
+ request.setRawHeader("Authorization", GenerateAuthorisationHeader());
+ request.setRawHeader("Accept", "application/json");
+
+ QNetworkReply* reply = network_->get(request);
+ NewClosure(reply, SIGNAL(finished()),
+ this, SLOT(CopySSOTokensFinished(QNetworkReply*)), reply);
+}
+
+void UbuntuOneAuthenticator::CopySSOTokensFinished(QNetworkReply* reply) {
+ reply->deleteLater();
+ qLog(Debug) << reply->readAll();
emit Finished();
}
diff --git a/src/internet/ubuntuoneauthenticator.h b/src/internet/ubuntuoneauthenticator.h
index eb853d5b8..053dbe5ae 100644
--- a/src/internet/ubuntuoneauthenticator.h
+++ b/src/internet/ubuntuoneauthenticator.h
@@ -17,11 +17,22 @@ class UbuntuOneAuthenticator : public QObject {
QString token() const { return token_; }
QString token_secret() const { return token_secret_; }
+ static QByteArray GenerateAuthorisationHeader(
+ const QString& consumer_key,
+ const QString& consumer_secret,
+ const QString& token,
+ const QString& token_secret);
+
signals:
void Finished();
private slots:
void AuthorisationFinished(QNetworkReply* reply);
+ void CopySSOTokensFinished(QNetworkReply* reply);
+
+ private:
+ void CopySSOTokens();
+ QByteArray GenerateAuthorisationHeader();
private:
NetworkAccessManager* network_;
diff --git a/src/internet/ubuntuoneservice.cpp b/src/internet/ubuntuoneservice.cpp
index bba1ac362..8cc78ef0e 100644
--- a/src/internet/ubuntuoneservice.cpp
+++ b/src/internet/ubuntuoneservice.cpp
@@ -1,6 +1,7 @@
#include "ubuntuoneservice.h"
#include
+#include
#include
@@ -21,10 +22,7 @@ const char* UbuntuOneService::kSettingsGroup = "Ubuntu One";
namespace {
static const char* kFileStorageEndpoint =
"https://one.ubuntu.com/api/file_storage/v1/~/Ubuntu One/";
-static const char* kOAuthSSOFinishedEndpoint =
- "https://one.ubuntu.com/oauth/sso-finished-so-get-tokens/";
static const char* kContentRoot = "https://files.one.ubuntu.com";
-static const char* kOAuthHeaderPrefix = "OAuth realm=\"\", ";
}
UbuntuOneService::UbuntuOneService(Application* app, InternetModel* parent)
@@ -52,6 +50,18 @@ void UbuntuOneService::LazyPopulate(QStandardItem* item) {
}
void UbuntuOneService::Connect() {
+ QSettings s;
+ s.beginGroup(kSettingsGroup);
+ if (s.contains("consumer_key")) {
+ consumer_key_ = s.value("consumer_key").toString();
+ consumer_secret_ = s.value("consumer_secret").toString();
+ token_ = s.value("token").toString();
+ token_secret_ = s.value("token_secret").toString();
+
+ RequestFileList();
+ return;
+ }
+
UbuntuOneAuthenticator* authenticator = new UbuntuOneAuthenticator;
authenticator->StartAuthorisation(
"Username",
@@ -62,36 +72,11 @@ void UbuntuOneService::Connect() {
}
QByteArray UbuntuOneService::GenerateAuthorisationHeader() {
- typedef QPair Param;
- QString timestamp = QString::number(
- QDateTime::currentMSecsSinceEpoch() / kMsecPerSec);
- QList parameters;
- parameters << Param("oauth_nonce", QString::number(qrand()))
- << Param("oauth_timestamp", timestamp)
- << Param("oauth_version", "1.0")
- << Param("oauth_consumer_key", consumer_key_)
- << Param("oauth_token", token_)
- << Param("oauth_signature_method", "PLAINTEXT");
- qSort(parameters.begin(), parameters.end());
- QStringList encoded_params;
- for (const Param& p : parameters) {
- encoded_params << QString("%1=%2").arg(p.first, p.second);
- }
-
- QString signing_key =
- consumer_secret_ + "&" + token_secret_;
- QByteArray signature = QUrl::toPercentEncoding(signing_key);
-
- // Construct authorisation header
- parameters << Param("oauth_signature", signature);
- QStringList header_params;
- for (const Param& p : parameters) {
- header_params << QString("%1=\"%2\"").arg(p.first, p.second);
- }
- QString authorisation_header = header_params.join(", ");
- authorisation_header.prepend(kOAuthHeaderPrefix);
-
- return authorisation_header.toAscii();
+ return UbuntuOneAuthenticator::GenerateAuthorisationHeader(
+ consumer_key_,
+ consumer_secret_,
+ token_,
+ token_secret_);
}
void UbuntuOneService::AuthenticationFinished(
@@ -103,19 +88,17 @@ void UbuntuOneService::AuthenticationFinished(
token_ = authenticator->token();
token_secret_ = authenticator->token_secret();
- QUrl sso_url(kOAuthSSOFinishedEndpoint);
- QNetworkRequest request(sso_url);
- request.setRawHeader("Authorization", GenerateAuthorisationHeader());
- request.setRawHeader("Accept", "application/json");
+ QSettings s;
+ s.beginGroup(kSettingsGroup);
+ s.setValue("consumer_key", consumer_key_);
+ s.setValue("consumer_secret", consumer_secret_);
+ s.setValue("token", token_);
+ s.setValue("token_secret", token_secret_);
- qLog(Debug) << "Sending SSO copy request";
- QNetworkReply* reply = network_->get(request);
- NewClosure(reply, SIGNAL(finished()),
- this, SLOT(SSORequestFinished(QNetworkReply*)), reply);
+ RequestFileList();
}
-void UbuntuOneService::SSORequestFinished(QNetworkReply* reply) {
- qLog(Debug) << Q_FUNC_INFO;
+void UbuntuOneService::RequestFileList() {
QUrl files_url(kFileStorageEndpoint);
files_url.addQueryItem("include_children", "true");
QNetworkRequest request(files_url);
diff --git a/src/internet/ubuntuoneservice.h b/src/internet/ubuntuoneservice.h
index 731e36ef1..756f8f51f 100644
--- a/src/internet/ubuntuoneservice.h
+++ b/src/internet/ubuntuoneservice.h
@@ -23,11 +23,11 @@ class UbuntuOneService : public InternetService {
private slots:
void AuthenticationFinished(UbuntuOneAuthenticator* authenticator);
- void SSORequestFinished(QNetworkReply* reply);
void FileListRequestFinished(QNetworkReply* reply);
private:
void Connect();
+ void RequestFileList();
private:
QByteArray GenerateAuthorisationHeader();
diff --git a/src/internet/ubuntuonesettingspage.cpp b/src/internet/ubuntuonesettingspage.cpp
new file mode 100644
index 000000000..cb12e5d34
--- /dev/null
+++ b/src/internet/ubuntuonesettingspage.cpp
@@ -0,0 +1,74 @@
+#include "ubuntuonesettingspage.h"
+
+#include "ui_ubuntuonesettingspage.h"
+
+#include "core/application.h"
+#include "core/closure.h"
+#include "core/logging.h"
+#include "internet/internetmodel.h"
+#include "internet/ubuntuoneauthenticator.h"
+#include "internet/ubuntuoneservice.h"
+
+UbuntuOneSettingsPage::UbuntuOneSettingsPage(SettingsDialog* parent)
+ : SettingsPage(parent),
+ ui_(new Ui::UbuntuOneSettingsPage),
+ service_(dialog()->app()->internet_model()->Service()),
+ authenticated_(false) {
+ ui_->setupUi(this);
+ ui_->login_state->AddCredentialGroup(ui_->login_container);
+ connect(ui_->login_button, SIGNAL(clicked()), SLOT(LoginClicked()));
+
+ dialog()->installEventFilter(this);
+}
+
+void UbuntuOneSettingsPage::Load() {
+ QSettings s;
+ s.beginGroup(UbuntuOneService::kSettingsGroup);
+
+ const QString user_email = s.value("user_email").toString();
+ if (!user_email.isEmpty()) {
+ ui_->login_state->SetLoggedIn(LoginStateWidget::LoggedIn, user_email);
+ ui_->username->setText(user_email);
+ }
+}
+
+void UbuntuOneSettingsPage::Save() {
+ QSettings s;
+ s.beginGroup(UbuntuOneService::kSettingsGroup);
+
+ if (authenticated_) {
+ s.setValue("user_email", ui_->username->text());
+ }
+}
+
+void UbuntuOneSettingsPage::LoginClicked() {
+ ui_->login_button->setEnabled(false);
+ QString username = ui_->username->text();
+ QString password = ui_->password->text();
+
+ UbuntuOneAuthenticator* authenticator = new UbuntuOneAuthenticator;
+ authenticator->StartAuthorisation(username, password);
+ NewClosure(authenticator, SIGNAL(Finished()),
+ this, SLOT(Connected(UbuntuOneAuthenticator*)), authenticator);
+ NewClosure(authenticator, SIGNAL(Finished()),
+ service_, SLOT(AuthenticationFinished(UbuntuOneAuthenticator*)),
+ authenticator);
+}
+
+void UbuntuOneSettingsPage::LogoutClicked() {
+
+}
+
+void UbuntuOneSettingsPage::Connected(UbuntuOneAuthenticator* authenticator) {
+ ui_->login_state->SetLoggedIn(LoginStateWidget::LoggedIn, ui_->username->text());
+ authenticated_ = true;
+}
+
+bool UbuntuOneSettingsPage::eventFilter(QObject* object, QEvent* event) {
+ if (object == dialog() && event->type() == QEvent::Enter) {
+ ui_->login_button->setEnabled(true);
+ return false;
+ }
+
+ return SettingsPage::eventFilter(object, event);
+}
diff --git a/src/internet/ubuntuonesettingspage.h b/src/internet/ubuntuonesettingspage.h
new file mode 100644
index 000000000..855fc733e
--- /dev/null
+++ b/src/internet/ubuntuonesettingspage.h
@@ -0,0 +1,33 @@
+#ifndef UBUNTUONESETTINGSPAGE_H
+#define UBUNTUONESETTINGSPAGE_H
+
+#include "ui/settingspage.h"
+
+class UbuntuOneAuthenticator;
+class UbuntuOneService;
+class Ui_UbuntuOneSettingsPage;
+
+class UbuntuOneSettingsPage : public SettingsPage {
+ Q_OBJECT
+ public:
+ UbuntuOneSettingsPage(SettingsDialog* parent = 0);
+
+ void Load();
+ void Save();
+
+ // QObject
+ bool eventFilter(QObject* object, QEvent* event);
+
+ private slots:
+ void LoginClicked();
+ void LogoutClicked();
+ void Connected(UbuntuOneAuthenticator* authenticator);
+
+ private:
+ Ui_UbuntuOneSettingsPage* ui_;
+ UbuntuOneService* service_;
+
+ bool authenticated_;
+};
+
+#endif // UBUNTUONESETTINGSPAGE_H
diff --git a/src/internet/ubuntuonesettingspage.ui b/src/internet/ubuntuonesettingspage.ui
new file mode 100644
index 000000000..be681d142
--- /dev/null
+++ b/src/internet/ubuntuonesettingspage.ui
@@ -0,0 +1,117 @@
+
+
+ UbuntuOneSettingsPage
+
+
+
+ 0
+ 0
+ 569
+ 491
+
+
+
+ Ubuntu One
+
+
+
+ :/providers/ubuntuone.png:/providers/ubuntuone.png
+
+
+ -
+
+
+ Clementine can play music that you have uploaded to Ubuntu One
+
+
+ true
+
+
+
+ -
+
+
+ -
+
+
+
+ 28
+
+
+ 0
+
+
+ 0
+
+
-
+
+
-
+
+
+ Login
+
+
+
+ -
+
+
+ Email address
+
+
+
+ -
+
+
+ Password
+
+
+ QLineEdit::Password
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 357
+
+
+
+
+
+
+
+
+ LoginStateWidget
+ QWidget
+ widgets/loginstatewidget.h
+ 1
+
+
+
+
+
+
+
diff --git a/src/ui/settingsdialog.cpp b/src/ui/settingsdialog.cpp
index 868d06452..e465867d9 100644
--- a/src/ui/settingsdialog.cpp
+++ b/src/ui/settingsdialog.cpp
@@ -37,6 +37,7 @@
#include "internet/digitallyimportedsettingspage.h"
#include "internet/groovesharksettingspage.h"
#include "internet/magnatunesettingspage.h"
+#include "internet/ubuntuonesettingspage.h"
#include "library/librarysettingspage.h"
#include "playlist/playlistview.h"
#include "podcasts/podcastsettingspage.h"
@@ -147,6 +148,8 @@ SettingsDialog::SettingsDialog(Application* app, BackgroundStreams* streams, QWi
AddPage(Page_GoogleDrive, new GoogleDriveSettingsPage(this), providers);
#endif
+ AddPage(Page_UbuntuOne, new UbuntuOneSettingsPage(this), providers);
+
#ifdef HAVE_SPOTIFY
AddPage(Page_Spotify, new SpotifySettingsPage(this), providers);
#endif
diff --git a/src/ui/settingsdialog.h b/src/ui/settingsdialog.h
index 3d73b5691..0e8d19498 100644
--- a/src/ui/settingsdialog.h
+++ b/src/ui/settingsdialog.h
@@ -77,6 +77,7 @@ public:
Page_Wiimotedev,
Page_Podcasts,
Page_GoogleDrive,
+ Page_UbuntuOne,
};
enum Role {