1 // Copyright (c) 2011 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/ui/webui/slideshow_ui.h" 6 7 #include "base/callback.h" 8 #include "base/memory/singleton.h" 9 #include "base/memory/weak_ptr.h" 10 #include "base/message_loop.h" 11 #include "base/path_service.h" 12 #include "base/string_piece.h" 13 #include "base/string_util.h" 14 #include "base/threading/thread.h" 15 #include "base/time.h" 16 #include "base/utf_string_conversions.h" 17 #include "base/values.h" 18 #include "chrome/browser/history/history_types.h" 19 #include "chrome/browser/metrics/user_metrics.h" 20 #include "chrome/browser/profiles/profile.h" 21 #include "chrome/browser/ui/webui/favicon_source.h" 22 #include "chrome/common/chrome_paths.h" 23 #include "chrome/common/jstemplate_builder.h" 24 #include "chrome/common/url_constants.h" 25 #include "content/browser/browser_thread.h" 26 #include "content/browser/tab_contents/tab_contents.h" 27 #include "grit/browser_resources.h" 28 #include "grit/chromium_strings.h" 29 #include "grit/generated_resources.h" 30 #include "grit/locale_settings.h" 31 #include "net/base/directory_lister.h" 32 #include "net/base/escape.h" 33 #include "ui/base/resource/resource_bundle.h" 34 35 static const char kPropertyPath[] = "path"; 36 static const char kPropertyTitle[] = "title"; 37 static const char kPropertyOffset[] = "currentOffset"; 38 static const char kPropertyDirectory[] = "isDirectory"; 39 40 class SlideshowUIHTMLSource : public ChromeURLDataManager::DataSource { 41 public: 42 SlideshowUIHTMLSource(); 43 44 // Called when the network layer has requested a resource underneath 45 // the path we registered. 46 virtual void StartDataRequest(const std::string& path, 47 bool is_incognito, 48 int request_id); 49 virtual std::string GetMimeType(const std::string&) const { 50 return "text/html"; 51 } 52 53 private: 54 ~SlideshowUIHTMLSource() {} 55 56 DISALLOW_COPY_AND_ASSIGN(SlideshowUIHTMLSource); 57 }; 58 59 // The handler for Javascript messages related to the "slideshow" view. 60 class SlideshowHandler : public net::DirectoryLister::DirectoryListerDelegate, 61 public WebUIMessageHandler, 62 public base::SupportsWeakPtr<SlideshowHandler> { 63 public: 64 SlideshowHandler(); 65 virtual ~SlideshowHandler(); 66 67 // Init work after Attach. 68 void Init(); 69 70 // DirectoryLister::DirectoryListerDelegate methods: 71 virtual void OnListFile( 72 const net::DirectoryLister::DirectoryListerData& data); 73 virtual void OnListDone(int error); 74 75 // WebUIMessageHandler implementation. 76 virtual WebUIMessageHandler* Attach(WebUI* web_ui); 77 virtual void RegisterMessages(); 78 79 void GetChildrenForPath(const FilePath& path, bool is_refresh); 80 81 // Callback for the "getChildren" message. 82 void HandleGetChildren(const ListValue* args); 83 84 void HandleRefreshDirectory(const ListValue* args); 85 86 private: 87 bool PathIsImageFile(const char* filename); 88 89 scoped_ptr<ListValue> filelist_value_; 90 FilePath currentpath_; 91 FilePath originalpath_; 92 Profile* profile_; 93 int counter_; 94 int currentOffset_; 95 scoped_refptr<net::DirectoryLister> lister_; 96 bool is_refresh_; 97 98 DISALLOW_COPY_AND_ASSIGN(SlideshowHandler); 99 }; 100 101 //////////////////////////////////////////////////////////////////////////////// 102 // 103 // SlideshowHTMLSource 104 // 105 //////////////////////////////////////////////////////////////////////////////// 106 107 SlideshowUIHTMLSource::SlideshowUIHTMLSource() 108 : DataSource(chrome::kChromeUISlideshowHost, MessageLoop::current()) { 109 } 110 111 void SlideshowUIHTMLSource::StartDataRequest(const std::string& path, 112 bool is_incognito, 113 int request_id) { 114 DictionaryValue localized_strings; 115 // TODO(dhg): Add stirings to localized strings, also add more strings 116 // that are currently hardcoded. 117 SetFontAndTextDirection(&localized_strings); 118 119 static const base::StringPiece slideshow_html( 120 ResourceBundle::GetSharedInstance().GetRawDataResource( 121 IDR_SLIDESHOW_HTML)); 122 const std::string full_html = jstemplate_builder::GetI18nTemplateHtml( 123 slideshow_html, &localized_strings); 124 125 scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); 126 html_bytes->data.resize(full_html.size()); 127 std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin()); 128 129 SendResponse(request_id, html_bytes); 130 } 131 132 //////////////////////////////////////////////////////////////////////////////// 133 // 134 // SlideshowHandler 135 // 136 //////////////////////////////////////////////////////////////////////////////// 137 SlideshowHandler::SlideshowHandler() 138 : profile_(NULL), 139 is_refresh_(false) { 140 lister_ = NULL; 141 } 142 143 SlideshowHandler::~SlideshowHandler() { 144 if (lister_.get()) { 145 lister_->Cancel(); 146 lister_->set_delegate(NULL); 147 } 148 } 149 150 WebUIMessageHandler* SlideshowHandler::Attach(WebUI* web_ui) { 151 profile_ = web_ui->GetProfile(); 152 // Create our favicon data source. 153 profile_->GetChromeURLDataManager()->AddDataSource( 154 new FaviconSource(profile_)); 155 return WebUIMessageHandler::Attach(web_ui); 156 } 157 158 void SlideshowHandler::Init() { 159 } 160 161 void SlideshowHandler::RegisterMessages() { 162 web_ui_->RegisterMessageCallback("getChildren", 163 NewCallback(this, &SlideshowHandler::HandleGetChildren)); 164 web_ui_->RegisterMessageCallback("refreshDirectory", 165 NewCallback(this, &SlideshowHandler::HandleRefreshDirectory)); 166 } 167 168 void SlideshowHandler::HandleRefreshDirectory(const ListValue* args) { 169 #if defined(OS_CHROMEOS) 170 std::string path = UTF16ToUTF8(ExtractStringValue(args)); 171 GetChildrenForPath(FilePath(path), true); 172 #endif 173 } 174 175 void SlideshowHandler::GetChildrenForPath(const FilePath& path, 176 bool is_refresh) { 177 filelist_value_.reset(new ListValue()); 178 currentpath_ = path; 179 180 if (lister_.get()) { 181 lister_->Cancel(); 182 lister_->set_delegate(NULL); 183 lister_ = NULL; 184 } 185 186 is_refresh_ = is_refresh; 187 if (file_util::EnsureEndsWithSeparator(¤tpath_) && 188 currentpath_.IsAbsolute()) { 189 lister_ = new net::DirectoryLister(currentpath_, this); 190 } else { 191 originalpath_ = currentpath_; 192 currentpath_ = currentpath_.DirName(); 193 lister_ = new net::DirectoryLister(currentpath_, this); 194 } 195 counter_ = 0; 196 currentOffset_ = -1; 197 lister_->Start(); 198 } 199 200 void SlideshowHandler::HandleGetChildren(const ListValue* args) { 201 #if defined(OS_CHROMEOS) 202 filelist_value_.reset(new ListValue()); 203 std::string path = UTF16ToUTF8(ExtractStringValue(args)); 204 GetChildrenForPath(FilePath(path), false); 205 #endif 206 } 207 208 bool SlideshowHandler::PathIsImageFile(const char* filename) { 209 #if defined(OS_CHROMEOS) 210 FilePath file = FilePath(filename); 211 std::string ext = file.Extension(); 212 ext = StringToLowerASCII(ext); 213 if (ext == ".jpg" || 214 ext == ".jpeg" || 215 ext == ".png" || 216 ext == ".gif") { 217 return true; 218 } else { 219 return false; 220 } 221 #else 222 return false; 223 #endif 224 } 225 226 void SlideshowHandler::OnListFile( 227 const net::DirectoryLister::DirectoryListerData& data) { 228 #if defined(OS_CHROMEOS) 229 if (data.info.filename[0] == '.') { 230 return; 231 } 232 if (!PathIsImageFile(data.info.filename.c_str())) { 233 return; 234 } 235 236 DictionaryValue* file_value = new DictionaryValue(); 237 238 file_value->SetString(kPropertyTitle, data.info.filename); 239 file_value->SetString(kPropertyPath, 240 currentpath_.Append(data.info.filename).value()); 241 file_value->SetBoolean(kPropertyDirectory, S_ISDIR(data.info.stat.st_mode)); 242 filelist_value_->Append(file_value); 243 std::string val; 244 file_value->GetString(kPropertyTitle, &val); 245 if (val == originalpath_.BaseName().value()) { 246 currentOffset_ = counter_; 247 } 248 counter_++; 249 #endif 250 } 251 252 void SlideshowHandler::OnListDone(int error) { 253 DictionaryValue info_value; 254 counter_ = 0; 255 if (!(file_util::EnsureEndsWithSeparator(&originalpath_) && 256 originalpath_.IsAbsolute()) && 257 currentOffset_ != -1) { 258 info_value.SetInteger(kPropertyOffset, currentOffset_); 259 } 260 if (is_refresh_) { 261 info_value.SetString("functionCall", "refresh"); 262 } else { 263 info_value.SetString("functionCall", "getChildren"); 264 } 265 info_value.SetString(kPropertyPath, currentpath_.value()); 266 web_ui_->CallJavascriptFunction("browseFileResult", 267 info_value, *(filelist_value_.get())); 268 } 269 270 //////////////////////////////////////////////////////////////////////////////// 271 // 272 // SlideshowUI 273 // 274 //////////////////////////////////////////////////////////////////////////////// 275 276 SlideshowUI::SlideshowUI(TabContents* contents) : WebUI(contents) { 277 SlideshowHandler* handler = new SlideshowHandler(); 278 AddMessageHandler((handler)->Attach(this)); 279 handler->Init(); 280 SlideshowUIHTMLSource* html_source = new SlideshowUIHTMLSource(); 281 282 // Set up the chrome://slideshow/ source. 283 contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source); 284 } 285