• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/chromeos/extensions/wallpaper_api.h"
6 
7 #include "ash/desktop_background/desktop_background_controller.h"
8 #include "base/file_util.h"
9 #include "base/lazy_instance.h"
10 #include "base/path_service.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/threading/worker_pool.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/chromeos/login/user.h"
15 #include "chrome/browser/chromeos/login/user_manager.h"
16 #include "chrome/browser/chromeos/login/wallpaper_manager.h"
17 #include "chrome/common/chrome_paths.h"
18 #include "net/base/load_flags.h"
19 #include "net/url_request/url_fetcher.h"
20 #include "net/url_request/url_fetcher_delegate.h"
21 #include "url/gurl.h"
22 
23 using base::BinaryValue;
24 using content::BrowserThread;
25 
26 typedef base::Callback<void(net::URLRequestStatus::Status, const std::string&)>
27     FetchCallback;
28 
29 namespace set_wallpaper = extensions::api::wallpaper::SetWallpaper;
30 
31 namespace {
32 
33 class WallpaperFetcher : public net::URLFetcherDelegate {
34  public:
WallpaperFetcher()35   WallpaperFetcher() {}
36 
~WallpaperFetcher()37   virtual ~WallpaperFetcher() {}
38 
FetchWallpaper(const GURL & url,FetchCallback callback)39   void FetchWallpaper(const GURL& url, FetchCallback callback) {
40     CancelPreviousFetch();
41     callback_ = callback;
42     url_fetcher_.reset(net::URLFetcher::Create(url,
43                                                net::URLFetcher::GET,
44                                                this));
45     url_fetcher_->SetRequestContext(
46         g_browser_process->system_request_context());
47     url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE);
48     url_fetcher_->Start();
49   }
50 
51  private:
52   // URLFetcherDelegate overrides:
OnURLFetchComplete(const net::URLFetcher * source)53   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE {
54     net::URLRequestStatus::Status status = source->GetStatus().status();
55     std::string response;
56     if (status == net::URLRequestStatus::SUCCESS) {
57       url_fetcher_->GetResponseAsString(&response);
58     } else {
59       response = source->GetStatus().error();
60     }
61     url_fetcher_.reset();
62     callback_.Run(status, response);
63   }
64 
CancelPreviousFetch()65   void CancelPreviousFetch() {
66     if (url_fetcher_.get()) {
67       std::string error = base::StringPrintf(
68           "Downloading wallpaper %s is canceled.",
69           url_fetcher_->GetOriginalURL().ExtractFileName().c_str());
70       callback_.Run(net::URLRequestStatus::CANCELED, error);
71       url_fetcher_.reset();
72     }
73   }
74 
75   scoped_ptr<net::URLFetcher> url_fetcher_;
76   FetchCallback callback_;
77 };
78 
79 base::LazyInstance<WallpaperFetcher> g_wallpaper_fetcher =
80     LAZY_INSTANCE_INITIALIZER;
81 
82 }  // namespace
83 
WallpaperSetWallpaperFunction()84 WallpaperSetWallpaperFunction::WallpaperSetWallpaperFunction() {
85 }
86 
~WallpaperSetWallpaperFunction()87 WallpaperSetWallpaperFunction::~WallpaperSetWallpaperFunction() {
88 }
89 
RunImpl()90 bool WallpaperSetWallpaperFunction::RunImpl() {
91   params_ = set_wallpaper::Params::Create(*args_);
92   EXTENSION_FUNCTION_VALIDATE(params_);
93 
94   // Gets email address and username hash while at UI thread.
95   email_ = chromeos::UserManager::Get()->GetLoggedInUser()->email();
96   user_id_hash_ =
97       chromeos::UserManager::Get()->GetLoggedInUser()->username_hash();
98 
99   if (params_->details.wallpaper_data) {
100     StartDecode(*params_->details.wallpaper_data);
101   } else {
102     GURL wallpaper_url(*params_->details.url);
103     if (wallpaper_url.is_valid()) {
104     g_wallpaper_fetcher.Get().FetchWallpaper(
105         wallpaper_url,
106         base::Bind(&WallpaperSetWallpaperFunction::OnWallpaperFetched,
107                    this));
108     } else {
109       SetError("URL is invalid.");
110       SendResponse(false);
111     }
112   }
113   return true;
114 }
115 
OnWallpaperDecoded(const gfx::ImageSkia & wallpaper)116 void WallpaperSetWallpaperFunction::OnWallpaperDecoded(
117     const gfx::ImageSkia& wallpaper) {
118   chromeos::WallpaperManager* wallpaper_manager =
119       chromeos::WallpaperManager::Get();
120   chromeos::UserImage::RawImage raw_image(
121       params_->details.wallpaper_data->begin(),
122       params_->details.wallpaper_data->end());
123   chromeos::UserImage image(wallpaper, raw_image);
124   base::FilePath thumbnail_path = wallpaper_manager->GetCustomWallpaperPath(
125       chromeos::kThumbnailWallpaperSubDir,
126       user_id_hash_,
127       params_->details.name);
128 
129   sequence_token_ = BrowserThread::GetBlockingPool()->
130       GetNamedSequenceToken(chromeos::kWallpaperSequenceTokenName);
131   scoped_refptr<base::SequencedTaskRunner> task_runner =
132       BrowserThread::GetBlockingPool()->
133           GetSequencedTaskRunnerWithShutdownBehavior(sequence_token_,
134               base::SequencedWorkerPool::BLOCK_SHUTDOWN);
135   ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
136       set_wallpaper::Params::Details::ToString(params_->details.layout));
137   wallpaper_manager->SetCustomWallpaper(email_,
138                                         user_id_hash_,
139                                         params_->details.name,
140                                         layout,
141                                         chromeos::User::CUSTOMIZED,
142                                         image);
143   unsafe_wallpaper_decoder_ = NULL;
144 
145   if (params_->details.thumbnail) {
146     wallpaper.EnsureRepsForSupportedScales();
147     scoped_ptr<gfx::ImageSkia> deep_copy(wallpaper.DeepCopy());
148     // Generates thumbnail before call api function callback. We can then
149     // request thumbnail in the javascript callback.
150     task_runner->PostTask(FROM_HERE,
151         base::Bind(
152             &WallpaperSetWallpaperFunction::GenerateThumbnail,
153             this, thumbnail_path, base::Passed(&deep_copy)));
154   } else {
155     SendResponse(true);
156   }
157 }
158 
GenerateThumbnail(const base::FilePath & thumbnail_path,scoped_ptr<gfx::ImageSkia> image)159 void WallpaperSetWallpaperFunction::GenerateThumbnail(
160     const base::FilePath& thumbnail_path, scoped_ptr<gfx::ImageSkia> image) {
161   DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
162       sequence_token_));
163   chromeos::UserImage wallpaper(*image.get());
164   if (!base::PathExists(thumbnail_path.DirName()))
165     base::CreateDirectory(thumbnail_path.DirName());
166 
167   scoped_refptr<base::RefCountedBytes> data;
168   chromeos::WallpaperManager::Get()->ResizeWallpaper(
169       wallpaper,
170       ash::WALLPAPER_LAYOUT_STRETCH,
171       ash::kWallpaperThumbnailWidth,
172       ash::kWallpaperThumbnailHeight,
173       &data);
174   BrowserThread::PostTask(
175       BrowserThread::UI, FROM_HERE,
176       base::Bind(
177           &WallpaperSetWallpaperFunction::ThumbnailGenerated,
178           this, data));
179 }
180 
ThumbnailGenerated(base::RefCountedBytes * data)181 void WallpaperSetWallpaperFunction::ThumbnailGenerated(
182     base::RefCountedBytes* data) {
183   BinaryValue* result = BinaryValue::CreateWithCopiedBuffer(
184       reinterpret_cast<const char*>(data->front()), data->size());
185   SetResult(result);
186   SendResponse(true);
187 }
188 
OnWallpaperFetched(net::URLRequestStatus::Status status,const std::string & response)189 void WallpaperSetWallpaperFunction::OnWallpaperFetched(
190     net::URLRequestStatus::Status status, const std::string& response) {
191   if (status == net::URLRequestStatus::SUCCESS) {
192     params_->details.wallpaper_data.reset(new std::string(response));
193     StartDecode(*params_->details.wallpaper_data);
194   } else {
195     SetError(response);
196     SendResponse(false);
197   }
198 }
199