Commit a29136f7 authored by Ramya Nagarajan's avatar Ramya Nagarajan Committed by Commit Bot

[NTP] Adds service integration to request photos.

Adds a service request and callback to get Google Photos from an album.
An access token for the signed-in user with requisite scope is
obtained and used in the request.

Bug: 839152
Change-Id: I3b012b8cdba247d94052c774dd0b1ae1be070d14
Reviewed-on: https://chromium-review.googlesource.com/1114231Reviewed-by: default avatarChristian Dullweber <dullweber@chromium.org>
Reviewed-by: default avatarAlexei Svitkine <asvitkine@chromium.org>
Reviewed-by: default avatarMarc Treib <treib@chromium.org>
Commit-Queue: Ramya Nagarajan <ramyan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#574442}
parent 5d4bb6ed
...@@ -110,3 +110,30 @@ message PersonalAlbumsResponse { ...@@ -110,3 +110,30 @@ message PersonalAlbumsResponse {
// Set to true if there was an error on the server. // Set to true if there was an error on the server.
optional bool error_on_server = 5; optional bool error_on_server = 5;
} }
// The Photos API returns metadata about photos within an album as a
// SettingPreviewResponse. See NtpBackgroundService::FetchAlbumPhotos for the
// API's usage. This is a server-defined message.
message SettingPreviewResponse {
// Deprecated or unused tag numbers
reserved 1;
// A preview image for each photo.
message Preview { optional string preview_url = 1; }
repeated Preview preview = 2;
// A resume token can be used to get the next page of results.
optional string resume_token = 3;
// An error_msg is set when the status is not 'SUCCESS'.
optional ErrorCode status = 4 [default = SUCCESS];
optional string error_msg = 5;
}
// Server-defined ErrorCodes for the Photos API.
enum ErrorCode {
UNKNOWN = 0;
SUCCESS = 1;
BAD_REQUEST = 2;
SERVER_ERROR = 3;
}
...@@ -106,3 +106,27 @@ AlbumInfo AlbumInfo::CreateFromProto( ...@@ -106,3 +106,27 @@ AlbumInfo AlbumInfo::CreateFromProto(
return album_info; return album_info;
} }
AlbumPhoto::AlbumPhoto() = default;
// TODO(crbug.com/851990) Handle urls with existing image options.
AlbumPhoto::AlbumPhoto(const std::string& photo_url,
const std::string& default_image_options)
: thumbnail_photo_url(GURL(photo_url)),
photo_url(GURL(photo_url + ((photo_url.find('=') == std::string::npos)
? default_image_options
: std::string()))) {}
AlbumPhoto::AlbumPhoto(const AlbumPhoto&) = default;
AlbumPhoto::AlbumPhoto(AlbumPhoto&&) = default;
AlbumPhoto::~AlbumPhoto() = default;
AlbumPhoto& AlbumPhoto::operator=(const AlbumPhoto&) = default;
AlbumPhoto& AlbumPhoto::operator=(AlbumPhoto&&) = default;
bool operator==(const AlbumPhoto& lhs, const AlbumPhoto& rhs) {
return lhs.thumbnail_photo_url == rhs.thumbnail_photo_url &&
lhs.photo_url == rhs.photo_url;
}
bool operator!=(const AlbumPhoto& lhs, const AlbumPhoto& rhs) {
return !(lhs == rhs);
}
...@@ -87,9 +87,12 @@ struct AlbumInfo { ...@@ -87,9 +87,12 @@ struct AlbumInfo {
static AlbumInfo CreateFromProto(const ntp::background::AlbumMetaData& album); static AlbumInfo CreateFromProto(const ntp::background::AlbumMetaData& album);
// A unique identifier for the album. // A unique identifier for the album. This is required when requesting the
// album.
int64_t album_id; int64_t album_id;
// A generic photo container ID based on the photo provider. // A generic photo container ID based on the photo provider. For Google
// Photos, this corresponds to media keys for the collection. It is also
// required when requesting the album.
std::string photo_container_id; std::string photo_container_id;
// A human-readable name for the album. // A human-readable name for the album.
std::string album_name; std::string album_name;
...@@ -100,4 +103,27 @@ struct AlbumInfo { ...@@ -100,4 +103,27 @@ struct AlbumInfo {
bool operator==(const AlbumInfo& lhs, const AlbumInfo& rhs); bool operator==(const AlbumInfo& lhs, const AlbumInfo& rhs);
bool operator!=(const AlbumInfo& lhs, const AlbumInfo& rhs); bool operator!=(const AlbumInfo& lhs, const AlbumInfo& rhs);
// Represents a photo within an album.
struct AlbumPhoto {
AlbumPhoto();
// default_image_options are applied to the image.image_url() if options
// (specifying resolution, cropping, etc) are not already present.
AlbumPhoto(const std::string& photo_url,
const std::string& default_image_options);
AlbumPhoto(const AlbumPhoto&);
AlbumPhoto(AlbumPhoto&&);
~AlbumPhoto();
AlbumPhoto& operator=(const AlbumPhoto&);
AlbumPhoto& operator=(AlbumPhoto&&);
// The thumbnail image URL, typically lower resolution than the photo_url.
GURL thumbnail_photo_url;
// The image URL.
GURL photo_url;
};
bool operator==(const AlbumPhoto& lhs, const AlbumPhoto& rhs);
bool operator!=(const AlbumPhoto& lhs, const AlbumPhoto& rhs);
#endif // CHROME_BROWSER_SEARCH_BACKGROUND_NTP_BACKGROUND_DATA_H_ #endif // CHROME_BROWSER_SEARCH_BACKGROUND_NTP_BACKGROUND_DATA_H_
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "chrome/browser/search/background/ntp_background_data.h" #include "chrome/browser/search/background/ntp_background_data.h"
#include "chrome/browser/search/background/ntp_background_service_observer.h" #include "chrome/browser/search/background/ntp_background_service_observer.h"
#include "components/keyed_service/core/keyed_service.h" #include "components/keyed_service/core/keyed_service.h"
#include "net/base/url_util.h"
#include "url/gurl.h" #include "url/gurl.h"
class GoogleServiceAuthError; class GoogleServiceAuthError;
...@@ -39,6 +40,7 @@ class NtpBackgroundService : public KeyedService { ...@@ -39,6 +40,7 @@ class NtpBackgroundService : public KeyedService {
const base::Optional<GURL>& collections_api_url_override, const base::Optional<GURL>& collections_api_url_override,
const base::Optional<GURL>& collection_images_api_url_override, const base::Optional<GURL>& collection_images_api_url_override,
const base::Optional<GURL>& albums_api_url_override, const base::Optional<GURL>& albums_api_url_override,
const base::Optional<GURL>& photos_api_base_url_override,
const base::Optional<std::string>& image_options_override); const base::Optional<std::string>& image_options_override);
~NtpBackgroundService() override; ~NtpBackgroundService() override;
...@@ -61,6 +63,13 @@ class NtpBackgroundService : public KeyedService { ...@@ -61,6 +63,13 @@ class NtpBackgroundService : public KeyedService {
// called on the observers. // called on the observers.
void FetchAlbumInfo(); void FetchAlbumInfo();
// Initially requests an access token for the signed-in user, and then
// requests an asynchronous fetch of photos using the access token, if it is
// available. After the fetch completes, OnAlbumPhotosAvailable will be called
// on the observers.
void FetchAlbumPhotos(const std::string& album_id,
const std::string& photo_container_id);
// Add/remove observers. All observers must unregister themselves before the // Add/remove observers. All observers must unregister themselves before the
// NtpBackgroundService is destroyed. // NtpBackgroundService is destroyed.
void AddObserver(NtpBackgroundServiceObserver* observer); void AddObserver(NtpBackgroundServiceObserver* observer);
...@@ -79,21 +88,29 @@ class NtpBackgroundService : public KeyedService { ...@@ -79,21 +88,29 @@ class NtpBackgroundService : public KeyedService {
// Returns the currently cached AlbumInfo, if any. // Returns the currently cached AlbumInfo, if any.
const std::vector<AlbumInfo>& album_info() const { return album_info_; } const std::vector<AlbumInfo>& album_info() const { return album_info_; }
// Returns the currently cached AlbumPhotos, if any.
const std::vector<AlbumPhoto>& album_photos() const { return album_photos_; }
GURL GetCollectionsLoadURLForTesting() const; GURL GetCollectionsLoadURLForTesting() const;
GURL GetImagesURLForTesting() const; GURL GetImagesURLForTesting() const;
GURL GetAlbumsURLForTesting() const; GURL GetAlbumsURLForTesting() const;
GURL GetAlbumPhotosApiUrlForTesting(
const std::string& album_id,
const std::string& photo_container_id) const;
private: private:
GURL collections_api_url_; GURL collections_api_url_;
GURL collection_images_api_url_; GURL collection_images_api_url_;
GURL albums_api_url_; GURL albums_api_url_;
GURL photos_api_base_url_;
std::string image_options_; std::string image_options_;
// Used to download the proto from the Backdrop service. // Used to download the proto from the Backdrop service.
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
std::unique_ptr<network::SimpleURLLoader> collections_loader_; std::unique_ptr<network::SimpleURLLoader> collections_loader_;
std::unique_ptr<network::SimpleURLLoader> image_info_loader_; std::unique_ptr<network::SimpleURLLoader> collections_image_info_loader_;
std::unique_ptr<network::SimpleURLLoader> albums_loader_; std::unique_ptr<network::SimpleURLLoader> albums_loader_;
std::unique_ptr<network::SimpleURLLoader> albums_photo_info_loader_;
identity::IdentityManager* const identity_manager_; identity::IdentityManager* const identity_manager_;
// The current OAuth2 token fetcher. // The current OAuth2 token fetcher.
...@@ -112,22 +129,36 @@ class NtpBackgroundService : public KeyedService { ...@@ -112,22 +129,36 @@ class NtpBackgroundService : public KeyedService {
void OnCollectionImageInfoFetchComplete( void OnCollectionImageInfoFetchComplete(
const std::unique_ptr<std::string> response_body); const std::unique_ptr<std::string> response_body);
void GetAccessTokenCallback(GoogleServiceAuthError error, std::string token); void GetAccessTokenForAlbumCallback(GoogleServiceAuthError error,
std::string token);
// Callback that processes the response from the FetchAlbumInfo request, // Callback that processes the response from the FetchAlbumInfo request,
// refreshing the contents of album_info_ with server-provided data. // refreshing the contents of album_info_ with server-provided data.
void OnAlbumInfoFetchComplete( void OnAlbumInfoFetchComplete(
const std::unique_ptr<std::string> response_body); const std::unique_ptr<std::string> response_body);
void GetAccessTokenForPhotosCallback(GoogleServiceAuthError error,
std::string token);
// Callback that processes the response from SettingPreviewRequest, refreshing
// the contents of album_photos_ with server-provided data.
void OnAlbumPhotosFetchComplete(
const std::unique_ptr<std::string> response_body);
enum class FetchComplete { enum class FetchComplete {
// Indicates that asynchronous fetch of CollectionInfo has completed. // Indicates that asynchronous fetch of CollectionInfo has completed.
COLLECTION_INFO, COLLECTION_INFO,
// Indicates that asynchronous fetch of CollectionImages has completed. // Indicates that asynchronous fetch of CollectionImages has completed.
COLLECTION_IMAGE_INFO, COLLECTION_IMAGE_INFO,
// Indicates that asynchronous fetch of AlbumInfo has completed. // Indicates that asynchronous fetch of AlbumInfo has completed.
ALBUM_INFO ALBUM_INFO,
// Indicates that asynchronous fetch of AlbumPhotos has completed.
ALBUM_PHOTOS
}; };
void NotifyObservers(FetchComplete fetch_complete); void NotifyObservers(FetchComplete fetch_complete);
GURL GetAlbumPhotosApiUrl() const;
GURL FormatAlbumPhotosBaseApiUrl(const std::string& album_id,
const std::string& photo_container_id) const;
std::vector<CollectionInfo> collection_info_; std::vector<CollectionInfo> collection_info_;
...@@ -136,6 +167,10 @@ class NtpBackgroundService : public KeyedService { ...@@ -136,6 +167,10 @@ class NtpBackgroundService : public KeyedService {
std::vector<AlbumInfo> album_info_; std::vector<AlbumInfo> album_info_;
std::vector<AlbumPhoto> album_photos_;
std::string requested_album_id_;
std::string requested_photo_container_id_;
DISALLOW_COPY_AND_ASSIGN(NtpBackgroundService); DISALLOW_COPY_AND_ASSIGN(NtpBackgroundService);
}; };
......
...@@ -51,11 +51,14 @@ KeyedService* NtpBackgroundServiceFactory::BuildServiceInstanceFor( ...@@ -51,11 +51,14 @@ KeyedService* NtpBackgroundServiceFactory::BuildServiceInstanceFor(
features::kNtpBackgrounds, "background-collection-images-api-url"); features::kNtpBackgrounds, "background-collection-images-api-url");
std::string albums_api_url = base::GetFieldTrialParamValueByFeature( std::string albums_api_url = base::GetFieldTrialParamValueByFeature(
features::kNtpBackgrounds, "background-albums-api-url"); features::kNtpBackgrounds, "background-albums-api-url");
std::string photos_api_base_url = base::GetFieldTrialParamValueByFeature(
features::kNtpBackgrounds, "background-photos-api-url");
std::string image_options = base::GetFieldTrialParamValueByFeature( std::string image_options = base::GetFieldTrialParamValueByFeature(
features::kNtpBackgrounds, "background-collections-image-options"); features::kNtpBackgrounds, "background-collections-image-options");
base::Optional<GURL> collection_api_url_override; base::Optional<GURL> collection_api_url_override;
base::Optional<GURL> collection_images_api_url_override; base::Optional<GURL> collection_images_api_url_override;
base::Optional<GURL> albums_api_url_override; base::Optional<GURL> albums_api_url_override;
base::Optional<GURL> photos_api_base_url_override;
base::Optional<std::string> image_options_override; base::Optional<std::string> image_options_override;
if (!collections_api_url.empty()) { if (!collections_api_url.empty()) {
collection_api_url_override = GURL(collections_api_url); collection_api_url_override = GURL(collections_api_url);
...@@ -66,6 +69,9 @@ KeyedService* NtpBackgroundServiceFactory::BuildServiceInstanceFor( ...@@ -66,6 +69,9 @@ KeyedService* NtpBackgroundServiceFactory::BuildServiceInstanceFor(
if (!albums_api_url.empty()) { if (!albums_api_url.empty()) {
albums_api_url_override = GURL(albums_api_url); albums_api_url_override = GURL(albums_api_url);
} }
if (!photos_api_base_url.empty()) {
photos_api_base_url_override = GURL(photos_api_base_url);
}
if (!image_options.empty()) { if (!image_options.empty()) {
image_options_override = image_options; image_options_override = image_options;
} }
...@@ -80,5 +86,5 @@ KeyedService* NtpBackgroundServiceFactory::BuildServiceInstanceFor( ...@@ -80,5 +86,5 @@ KeyedService* NtpBackgroundServiceFactory::BuildServiceInstanceFor(
return new NtpBackgroundService( return new NtpBackgroundService(
identity_manager, url_loader_factory, collection_api_url_override, identity_manager, url_loader_factory, collection_api_url_override,
collection_images_api_url_override, albums_api_url_override, collection_images_api_url_override, albums_api_url_override,
image_options_override); photos_api_base_url_override, image_options_override);
} }
...@@ -9,26 +9,25 @@ ...@@ -9,26 +9,25 @@
class NtpBackgroundServiceObserver { class NtpBackgroundServiceObserver {
public: public:
// Called when the CollectionInfo is updated, usually as the result of a // Called when the CollectionInfo is updated, usually as the result of a
// FetchCollectionInfo() call on the service. Note that this is called after // FetchCollectionInfo() call on the service. You can get the new data via
// each FetchCollectionInfo(), even if the network request failed, or if it // NtpBackgroundService::collection_info().
// didn't result in an actual change to the cached data. You can get the new
// data via NtpBackgroundService::collection_info().
virtual void OnCollectionInfoAvailable() = 0; virtual void OnCollectionInfoAvailable() = 0;
// Called when the CollectionImages are updated, usually as the result of a // Called when the CollectionImages are updated, usually as the result of a
// FetchCollectionImageInfo() call on the service. Note that this is called // FetchCollectionImageInfo() call on the service. You can get the new data
// after each FetchCollectionImage(), even if the network request failed, or // via NtpBackgroundService::collection_images().
// if it didn't result in an actual change to the cached data. You can get the
// new data via NtpBackgroundService::collection_images().
virtual void OnCollectionImagesAvailable() = 0; virtual void OnCollectionImagesAvailable() = 0;
// Called when the AlbumInfo is updated, usually as the result of a // Called when the AlbumInfo is updated, usually as the result of a
// PersonalAlbumsRequestOption() call on the service. Note that this is called // PersonalAlbumsRequestOption() call on the service. You can get the new
// after each FetchAlbumInfo(), even if the network request failed, or if it
// didn't result in an actual change to the cached data. You can get the new
// data via NtpBackgroundService::album_info(). // data via NtpBackgroundService::album_info().
virtual void OnAlbumInfoAvailable() = 0; virtual void OnAlbumInfoAvailable() = 0;
// Called when the AlbumPhotos are updated, usually as the result of a
// SettingPreviewRequest() call on the service. You can get the new data via
// NtpBackgroundService::album_photos().
virtual void OnAlbumPhotosAvailable() = 0;
// Called when the OnNtpBackgroundService is shutting down. Observers that // Called when the OnNtpBackgroundService is shutting down. Observers that
// might outlive the service should use this to unregister themselves, and // might outlive the service should use this to unregister themselves, and
// clear out any pointers to the service they might hold. // clear out any pointers to the service they might hold.
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "url/gurl.h" #include "url/gurl.h"
using testing::Eq; using testing::Eq;
using testing::StartsWith;
namespace { namespace {
...@@ -46,7 +47,8 @@ class NtpBackgroundServiceTest : public testing::Test { ...@@ -46,7 +47,8 @@ class NtpBackgroundServiceTest : public testing::Test {
service_ = std::make_unique<NtpBackgroundService>( service_ = std::make_unique<NtpBackgroundService>(
identity_env_.identity_manager(), test_shared_loader_factory_, identity_env_.identity_manager(), test_shared_loader_factory_,
base::nullopt, base::nullopt, base::nullopt, kImageOptions); base::nullopt, base::nullopt, base::nullopt, base::nullopt,
kImageOptions);
} }
void SetUpResponseWithData(const GURL& load_url, void SetUpResponseWithData(const GURL& load_url,
...@@ -80,11 +82,10 @@ TEST_F(NtpBackgroundServiceTest, CollectionInfoNetworkError) { ...@@ -80,11 +82,10 @@ TEST_F(NtpBackgroundServiceTest, CollectionInfoNetworkError) {
ASSERT_TRUE(service()->collection_info().empty()); ASSERT_TRUE(service()->collection_info().empty());
base::RunLoop loop;
service()->FetchCollectionInfo(); service()->FetchCollectionInfo();
loop.RunUntilIdle(); base::RunLoop().RunUntilIdle();
ASSERT_TRUE(service()->collection_info().empty()); EXPECT_TRUE(service()->collection_info().empty());
} }
TEST_F(NtpBackgroundServiceTest, BadCollectionsResponse) { TEST_F(NtpBackgroundServiceTest, BadCollectionsResponse) {
...@@ -93,9 +94,8 @@ TEST_F(NtpBackgroundServiceTest, BadCollectionsResponse) { ...@@ -93,9 +94,8 @@ TEST_F(NtpBackgroundServiceTest, BadCollectionsResponse) {
ASSERT_TRUE(service()->collection_info().empty()); ASSERT_TRUE(service()->collection_info().empty());
base::RunLoop loop;
service()->FetchCollectionInfo(); service()->FetchCollectionInfo();
loop.RunUntilIdle(); base::RunLoop().RunUntilIdle();
EXPECT_TRUE(service()->collection_info().empty()); EXPECT_TRUE(service()->collection_info().empty());
} }
...@@ -115,9 +115,8 @@ TEST_F(NtpBackgroundServiceTest, GoodCollectionsResponse) { ...@@ -115,9 +115,8 @@ TEST_F(NtpBackgroundServiceTest, GoodCollectionsResponse) {
ASSERT_TRUE(service()->collection_info().empty()); ASSERT_TRUE(service()->collection_info().empty());
base::RunLoop loop;
service()->FetchCollectionInfo(); service()->FetchCollectionInfo();
loop.RunUntilIdle(); base::RunLoop().RunUntilIdle();
CollectionInfo collection_info; CollectionInfo collection_info;
collection_info.collection_id = collection.collection_id(); collection_info.collection_id = collection.collection_id();
...@@ -133,11 +132,10 @@ TEST_F(NtpBackgroundServiceTest, CollectionImagesNetworkError) { ...@@ -133,11 +132,10 @@ TEST_F(NtpBackgroundServiceTest, CollectionImagesNetworkError) {
ASSERT_TRUE(service()->collection_images().empty()); ASSERT_TRUE(service()->collection_images().empty());
base::RunLoop loop;
service()->FetchCollectionImageInfo("shapes"); service()->FetchCollectionImageInfo("shapes");
loop.RunUntilIdle(); base::RunLoop().RunUntilIdle();
ASSERT_TRUE(service()->collection_images().empty()); EXPECT_TRUE(service()->collection_images().empty());
} }
TEST_F(NtpBackgroundServiceTest, BadCollectionImagesResponse) { TEST_F(NtpBackgroundServiceTest, BadCollectionImagesResponse) {
...@@ -146,9 +144,8 @@ TEST_F(NtpBackgroundServiceTest, BadCollectionImagesResponse) { ...@@ -146,9 +144,8 @@ TEST_F(NtpBackgroundServiceTest, BadCollectionImagesResponse) {
ASSERT_TRUE(service()->collection_images().empty()); ASSERT_TRUE(service()->collection_images().empty());
base::RunLoop loop;
service()->FetchCollectionImageInfo("shapes"); service()->FetchCollectionImageInfo("shapes");
loop.RunUntilIdle(); base::RunLoop().RunUntilIdle();
EXPECT_TRUE(service()->collection_images().empty()); EXPECT_TRUE(service()->collection_images().empty());
} }
...@@ -168,9 +165,8 @@ TEST_F(NtpBackgroundServiceTest, GoodCollectionImagesResponse) { ...@@ -168,9 +165,8 @@ TEST_F(NtpBackgroundServiceTest, GoodCollectionImagesResponse) {
ASSERT_TRUE(service()->collection_images().empty()); ASSERT_TRUE(service()->collection_images().empty());
base::RunLoop loop;
service()->FetchCollectionImageInfo("shapes"); service()->FetchCollectionImageInfo("shapes");
loop.RunUntilIdle(); base::RunLoop().RunUntilIdle();
CollectionImage collection_image; CollectionImage collection_image;
collection_image.collection_id = "shapes"; collection_image.collection_id = "shapes";
...@@ -211,12 +207,11 @@ TEST_F(NtpBackgroundServiceTest, MultipleRequests) { ...@@ -211,12 +207,11 @@ TEST_F(NtpBackgroundServiceTest, MultipleRequests) {
ASSERT_TRUE(service()->collection_info().empty()); ASSERT_TRUE(service()->collection_info().empty());
ASSERT_TRUE(service()->collection_images().empty()); ASSERT_TRUE(service()->collection_images().empty());
base::RunLoop loop;
service()->FetchCollectionInfo(); service()->FetchCollectionInfo();
service()->FetchCollectionImageInfo("shapes"); service()->FetchCollectionImageInfo("shapes");
// Subsequent requests are ignored while the loader is in use. // Subsequent requests are ignored while the loader is in use.
service()->FetchCollectionImageInfo("colors"); service()->FetchCollectionImageInfo("colors");
loop.RunUntilIdle(); base::RunLoop().RunUntilIdle();
CollectionInfo collection_info; CollectionInfo collection_info;
collection_info.collection_id = collection.collection_id(); collection_info.collection_id = collection.collection_id();
...@@ -241,11 +236,10 @@ TEST_F(NtpBackgroundServiceTest, AlbumInfoNetworkError) { ...@@ -241,11 +236,10 @@ TEST_F(NtpBackgroundServiceTest, AlbumInfoNetworkError) {
ASSERT_TRUE(service()->album_info().empty()); ASSERT_TRUE(service()->album_info().empty());
base::RunLoop loop;
service()->FetchAlbumInfo(); service()->FetchAlbumInfo();
loop.RunUntilIdle(); base::RunLoop().RunUntilIdle();
ASSERT_TRUE(service()->album_info().empty()); EXPECT_TRUE(service()->album_info().empty());
} }
TEST_F(NtpBackgroundServiceTest, BadAlbumsResponse) { TEST_F(NtpBackgroundServiceTest, BadAlbumsResponse) {
...@@ -254,9 +248,8 @@ TEST_F(NtpBackgroundServiceTest, BadAlbumsResponse) { ...@@ -254,9 +248,8 @@ TEST_F(NtpBackgroundServiceTest, BadAlbumsResponse) {
ASSERT_TRUE(service()->album_info().empty()); ASSERT_TRUE(service()->album_info().empty());
base::RunLoop loop;
service()->FetchAlbumInfo(); service()->FetchAlbumInfo();
loop.RunUntilIdle(); base::RunLoop().RunUntilIdle();
EXPECT_TRUE(service()->album_info().empty()); EXPECT_TRUE(service()->album_info().empty());
} }
...@@ -276,9 +269,8 @@ TEST_F(NtpBackgroundServiceTest, GoodAlbumsResponse) { ...@@ -276,9 +269,8 @@ TEST_F(NtpBackgroundServiceTest, GoodAlbumsResponse) {
ASSERT_TRUE(service()->album_info().empty()); ASSERT_TRUE(service()->album_info().empty());
base::RunLoop loop;
service()->FetchAlbumInfo(); service()->FetchAlbumInfo();
loop.RunUntilIdle(); base::RunLoop().RunUntilIdle();
AlbumInfo album_info; AlbumInfo album_info;
album_info.album_id = album.album_id(); album_info.album_id = album.album_id();
...@@ -289,3 +281,71 @@ TEST_F(NtpBackgroundServiceTest, GoodAlbumsResponse) { ...@@ -289,3 +281,71 @@ TEST_F(NtpBackgroundServiceTest, GoodAlbumsResponse) {
EXPECT_FALSE(service()->album_info().empty()); EXPECT_FALSE(service()->album_info().empty());
EXPECT_THAT(service()->album_info().at(0), Eq(album_info)); EXPECT_THAT(service()->album_info().at(0), Eq(album_info));
} }
TEST_F(NtpBackgroundServiceTest, AlbumPhotosNetworkError) {
SetUpResponseWithNetworkError(service()->GetAlbumPhotosApiUrlForTesting(
"album_id", "photo_container_id"));
ASSERT_TRUE(service()->album_photos().empty());
service()->FetchAlbumPhotos("album_id", "photo_container_id");
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(service()->album_photos().empty());
}
TEST_F(NtpBackgroundServiceTest, BadAlbumPhotosResponse) {
SetUpResponseWithData(service()->GetAlbumPhotosApiUrlForTesting(
"album_id", "photo_container_id"),
"bad serialized SettingPreviewResponse");
ASSERT_TRUE(service()->album_photos().empty());
service()->FetchAlbumPhotos("album_id", "photo_container_id");
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(service()->album_photos().empty());
}
TEST_F(NtpBackgroundServiceTest, AlbumPhotoErrorResponse) {
ntp::background::SettingPreviewResponse response;
response.set_status(ntp::background::ErrorCode::SERVER_ERROR);
response.set_error_msg("server error");
std::string response_string;
response.SerializeToString(&response_string);
SetUpResponseWithData(service()->GetAlbumPhotosApiUrlForTesting(
"album_id", "photo_container_id"),
response_string);
ASSERT_TRUE(service()->album_photos().empty());
service()->FetchAlbumPhotos("album_id", "photo_container_id");
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(service()->album_photos().empty());
}
TEST_F(NtpBackgroundServiceTest, GoodAlbumPhotosResponse) {
ntp::background::SettingPreviewResponse::Preview preview;
preview.set_preview_url("https://wallpapers.co/some_image");
ntp::background::SettingPreviewResponse response;
*response.add_preview() = preview;
std::string response_string;
response.SerializeToString(&response_string);
SetUpResponseWithData(service()->GetAlbumPhotosApiUrlForTesting(
"album_id", "photo_container_id"),
response_string);
ASSERT_TRUE(service()->album_photos().empty());
service()->FetchAlbumPhotos("album_id", "photo_container_id");
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(service()->album_photos().empty());
EXPECT_THAT(service()->album_photos().at(0).thumbnail_photo_url.spec(),
StartsWith(preview.preview_url()));
EXPECT_THAT(service()->album_photos().at(0).photo_url.spec(),
StartsWith(preview.preview_url()));
}
...@@ -321,6 +321,20 @@ base::Value ConvertAlbumInfoToDict(const std::vector<AlbumInfo>& album_info) { ...@@ -321,6 +321,20 @@ base::Value ConvertAlbumInfoToDict(const std::vector<AlbumInfo>& album_info) {
return albums; return albums;
} }
base::Value ConvertAlbumPhotosToDict(
const std::vector<AlbumPhoto>& album_photos) {
base::Value photos(base::Value::Type::LIST);
photos.GetList().reserve(album_photos.size());
for (const AlbumPhoto& photo : album_photos) {
base::Value dict(base::Value::Type::DICTIONARY);
dict.SetKey("thumbnail_photo_url",
base::Value(photo.thumbnail_photo_url.spec()));
dict.SetKey("photo_url", base::Value(photo.photo_url.spec()));
photos.GetList().push_back(std::move(dict));
}
return photos;
}
std::unique_ptr<base::DictionaryValue> ConvertOGBDataToDict( std::unique_ptr<base::DictionaryValue> ConvertOGBDataToDict(
const OneGoogleBarData& og) { const OneGoogleBarData& og) {
auto result = std::make_unique<base::DictionaryValue>(); auto result = std::make_unique<base::DictionaryValue>();
...@@ -673,7 +687,7 @@ void LocalNtpSource::StartDataRequest( ...@@ -673,7 +687,7 @@ void LocalNtpSource::StartDataRequest(
callback); callback);
ntp_background_service_->FetchAlbumInfo(); ntp_background_service_->FetchAlbumInfo();
} else { } else {
// If there's no "collection_type" param, default to getting collections. // If collection_type is not "album", default to getting collections.
// TODO(ramyan): Explicitly require a collection_type when frontend // TODO(ramyan): Explicitly require a collection_type when frontend
// supports it. // supports it.
ntp_background_collections_requests_.emplace_back(base::TimeTicks::Now(), ntp_background_collections_requests_.emplace_back(base::TimeTicks::Now(),
...@@ -688,6 +702,28 @@ void LocalNtpSource::StartDataRequest( ...@@ -688,6 +702,28 @@ void LocalNtpSource::StartDataRequest(
callback.Run(nullptr); callback.Run(nullptr);
return; return;
} }
std::string collection_type_param;
GURL path_url = GURL(chrome::kChromeSearchLocalNtpUrl).Resolve(path);
if (net::GetValueForKeyInQuery(path_url, "collection_type",
&collection_type_param) &&
(collection_type_param == "album")) {
std::string album_id_param;
std::string photo_container_id_param;
if (!net::GetValueForKeyInQuery(path_url, "album_id", &album_id_param) ||
!net::GetValueForKeyInQuery(path_url, "photo_container_id",
&photo_container_id_param)) {
callback.Run(nullptr);
return;
}
ntp_background_photos_requests_.emplace_back(base::TimeTicks::Now(),
callback);
ntp_background_service_->FetchAlbumPhotos(album_id_param,
photo_container_id_param);
} else {
// If collection_type is not "album", default to getting images for a
// collection.
// TODO(ramyan): Explicitly require a collection_type when frontend
// supports it.
std::string collection_id_param; std::string collection_id_param;
GURL path_url = GURL(chrome::kChromeSearchLocalNtpUrl).Resolve(path); GURL path_url = GURL(chrome::kChromeSearchLocalNtpUrl).Resolve(path);
if (net::GetValueForKeyInQuery(path_url, "collection_id", if (net::GetValueForKeyInQuery(path_url, "collection_id",
...@@ -698,6 +734,7 @@ void LocalNtpSource::StartDataRequest( ...@@ -698,6 +734,7 @@ void LocalNtpSource::StartDataRequest(
} else { } else {
callback.Run(nullptr); callback.Run(nullptr);
} }
}
return; return;
} }
...@@ -916,6 +953,30 @@ void LocalNtpSource::OnAlbumInfoAvailable() { ...@@ -916,6 +953,30 @@ void LocalNtpSource::OnAlbumInfoAvailable() {
ntp_background_albums_requests_.clear(); ntp_background_albums_requests_.clear();
} }
void LocalNtpSource::OnAlbumPhotosAvailable() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (ntp_background_photos_requests_.empty())
return;
scoped_refptr<base::RefCountedString> result;
std::string js;
base::JSONWriter::Write(
ConvertAlbumPhotosToDict(ntp_background_service_->album_photos()), &js);
js = "var photos = " + js + ";";
result = base::RefCountedString::TakeString(&js);
base::TimeTicks now = base::TimeTicks::Now();
for (const auto& request : ntp_background_photos_requests_) {
request.callback.Run(result);
base::TimeDelta delta = now - request.start_time;
UMA_HISTOGRAM_MEDIUM_TIMES(
"NewTabPage.BackgroundService.Photos.RequestLatency", delta);
// TODO(ramyan): Define and capture latency for failed requests.
}
ntp_background_photos_requests_.clear();
}
void LocalNtpSource::OnNtpBackgroundServiceShuttingDown() { void LocalNtpSource::OnNtpBackgroundServiceShuttingDown() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
......
...@@ -92,6 +92,7 @@ class LocalNtpSource : public content::URLDataSource, ...@@ -92,6 +92,7 @@ class LocalNtpSource : public content::URLDataSource,
void OnCollectionInfoAvailable() override; void OnCollectionInfoAvailable() override;
void OnCollectionImagesAvailable() override; void OnCollectionImagesAvailable() override;
void OnAlbumInfoAvailable() override; void OnAlbumInfoAvailable() override;
void OnAlbumPhotosAvailable() override;
void OnNtpBackgroundServiceShuttingDown() override; void OnNtpBackgroundServiceShuttingDown() override;
// Overridden from OneGoogleBarServiceObserver: // Overridden from OneGoogleBarServiceObserver:
...@@ -105,6 +106,7 @@ class LocalNtpSource : public content::URLDataSource, ...@@ -105,6 +106,7 @@ class LocalNtpSource : public content::URLDataSource,
std::vector<NtpBackgroundRequest> ntp_background_collections_requests_; std::vector<NtpBackgroundRequest> ntp_background_collections_requests_;
std::vector<NtpBackgroundRequest> ntp_background_image_info_requests_; std::vector<NtpBackgroundRequest> ntp_background_image_info_requests_;
std::vector<NtpBackgroundRequest> ntp_background_albums_requests_; std::vector<NtpBackgroundRequest> ntp_background_albums_requests_;
std::vector<NtpBackgroundRequest> ntp_background_photos_requests_;
NtpBackgroundService* ntp_background_service_; NtpBackgroundService* ntp_background_service_;
......
...@@ -59101,6 +59101,16 @@ uploading your change for review. ...@@ -59101,6 +59101,16 @@ uploading your change for review.
</summary> </summary>
</histogram> </histogram>
<histogram name="NewTabPage.BackgroundService.Photos.RequestLatency" units="ms"
expires_after="M74">
<owner>ramyan@chromium.org</owner>
<owner>yyushkina@chromium.org</owner>
<summary>
The time it took until a request from the New Tab Page for Google Photos (in
a specific album) was served.
</summary>
</histogram>
<histogram name="NewTabPage.BookmarkActionAndroid" <histogram name="NewTabPage.BookmarkActionAndroid"
enum="NewTabPageBookmarkActionAndroid"> enum="NewTabPageBookmarkActionAndroid">
<obsolete> <obsolete>
...@@ -123,6 +123,7 @@ Refer to README.md for content description and update process. ...@@ -123,6 +123,7 @@ Refer to README.md for content description and update process.
<item id="gcm_unregistration" hash_code="119542033" type="0" content_hash_code="30144127" os_list="linux,windows" file_path="google_apis/gcm/engine/unregistration_request.cc"/> <item id="gcm_unregistration" hash_code="119542033" type="0" content_hash_code="30144127" os_list="linux,windows" file_path="google_apis/gcm/engine/unregistration_request.cc"/>
<item id="geo_language_provider" hash_code="52821843" type="1" second_id="96590038" content_hash_code="104675663" os_list="linux,windows" semantics_fields="1" policy_fields="3,4" file_path="components/language/content/browser/geo_language_provider.cc"/> <item id="geo_language_provider" hash_code="52821843" type="1" second_id="96590038" content_hash_code="104675663" os_list="linux,windows" semantics_fields="1" policy_fields="3,4" file_path="components/language/content/browser/geo_language_provider.cc"/>
<item id="google_photos_album_names_download" hash_code="65075134" type="0" content_hash_code="124531309" os_list="linux,windows" file_path="chrome/browser/search/background/ntp_background_service.cc"/> <item id="google_photos_album_names_download" hash_code="65075134" type="0" content_hash_code="124531309" os_list="linux,windows" file_path="chrome/browser/search/background/ntp_background_service.cc"/>
<item id="google_photos_metadata_download" hash_code="93441068" type="0" content_hash_code="48786223" os_list="linux,windows" file_path="chrome/browser/search/background/ntp_background_service.cc"/>
<item id="google_url_tracker" hash_code="5492492" type="0" content_hash_code="54474899" os_list="linux,windows" file_path="components/google/core/browser/google_url_tracker.cc"/> <item id="google_url_tracker" hash_code="5492492" type="0" content_hash_code="54474899" os_list="linux,windows" file_path="components/google/core/browser/google_url_tracker.cc"/>
<item id="headless_url_request" hash_code="29865866" type="0" deprecated="2018-07-10" content_hash_code="76700151" file_path=""/> <item id="headless_url_request" hash_code="29865866" type="0" deprecated="2018-07-10" content_hash_code="76700151" file_path=""/>
<item id="history_notice_utils_notice" hash_code="102595701" type="1" second_id="110307337" content_hash_code="130829410" os_list="linux,windows" semantics_fields="2,3,4" policy_fields="4" file_path="components/browsing_data/core/history_notice_utils.cc"/> <item id="history_notice_utils_notice" hash_code="102595701" type="1" second_id="110307337" content_hash_code="130829410" os_list="linux,windows" semantics_fields="2,3,4" policy_fields="4" file_path="components/browsing_data/core/history_notice_utils.cc"/>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment