// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/ui/webui/slideshow_ui.h" #include "base/callback.h" #include "base/memory/singleton.h" #include "base/memory/weak_ptr.h" #include "base/message_loop.h" #include "base/path_service.h" #include "base/string_piece.h" #include "base/string_util.h" #include "base/threading/thread.h" #include "base/time.h" #include "base/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/history/history_types.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/favicon_source.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/jstemplate_builder.h" #include "chrome/common/url_constants.h" #include "content/browser/browser_thread.h" #include "content/browser/tab_contents/tab_contents.h" #include "grit/browser_resources.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" #include "net/base/directory_lister.h" #include "net/base/escape.h" #include "ui/base/resource/resource_bundle.h" static const char kPropertyPath[] = "path"; static const char kPropertyTitle[] = "title"; static const char kPropertyOffset[] = "currentOffset"; static const char kPropertyDirectory[] = "isDirectory"; class SlideshowUIHTMLSource : public ChromeURLDataManager::DataSource { public: SlideshowUIHTMLSource(); // Called when the network layer has requested a resource underneath // the path we registered. virtual void StartDataRequest(const std::string& path, bool is_incognito, int request_id); virtual std::string GetMimeType(const std::string&) const { return "text/html"; } private: ~SlideshowUIHTMLSource() {} DISALLOW_COPY_AND_ASSIGN(SlideshowUIHTMLSource); }; // The handler for Javascript messages related to the "slideshow" view. class SlideshowHandler : public net::DirectoryLister::DirectoryListerDelegate, public WebUIMessageHandler, public base::SupportsWeakPtr<SlideshowHandler> { public: SlideshowHandler(); virtual ~SlideshowHandler(); // Init work after Attach. void Init(); // DirectoryLister::DirectoryListerDelegate methods: virtual void OnListFile( const net::DirectoryLister::DirectoryListerData& data); virtual void OnListDone(int error); // WebUIMessageHandler implementation. virtual WebUIMessageHandler* Attach(WebUI* web_ui); virtual void RegisterMessages(); void GetChildrenForPath(const FilePath& path, bool is_refresh); // Callback for the "getChildren" message. void HandleGetChildren(const ListValue* args); void HandleRefreshDirectory(const ListValue* args); private: bool PathIsImageFile(const char* filename); scoped_ptr<ListValue> filelist_value_; FilePath currentpath_; FilePath originalpath_; Profile* profile_; int counter_; int currentOffset_; scoped_refptr<net::DirectoryLister> lister_; bool is_refresh_; DISALLOW_COPY_AND_ASSIGN(SlideshowHandler); }; //////////////////////////////////////////////////////////////////////////////// // // SlideshowHTMLSource // //////////////////////////////////////////////////////////////////////////////// SlideshowUIHTMLSource::SlideshowUIHTMLSource() : DataSource(chrome::kChromeUISlideshowHost, MessageLoop::current()) { } void SlideshowUIHTMLSource::StartDataRequest(const std::string& path, bool is_incognito, int request_id) { DictionaryValue localized_strings; // TODO(dhg): Add stirings to localized strings, also add more strings // that are currently hardcoded. SetFontAndTextDirection(&localized_strings); static const base::StringPiece slideshow_html( ResourceBundle::GetSharedInstance().GetRawDataResource( IDR_SLIDESHOW_HTML)); const std::string full_html = jstemplate_builder::GetI18nTemplateHtml( slideshow_html, &localized_strings); scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); html_bytes->data.resize(full_html.size()); std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin()); SendResponse(request_id, html_bytes); } //////////////////////////////////////////////////////////////////////////////// // // SlideshowHandler // //////////////////////////////////////////////////////////////////////////////// SlideshowHandler::SlideshowHandler() : profile_(NULL), is_refresh_(false) { lister_ = NULL; } SlideshowHandler::~SlideshowHandler() { if (lister_.get()) { lister_->Cancel(); lister_->set_delegate(NULL); } } WebUIMessageHandler* SlideshowHandler::Attach(WebUI* web_ui) { profile_ = web_ui->GetProfile(); // Create our favicon data source. profile_->GetChromeURLDataManager()->AddDataSource( new FaviconSource(profile_)); return WebUIMessageHandler::Attach(web_ui); } void SlideshowHandler::Init() { } void SlideshowHandler::RegisterMessages() { web_ui_->RegisterMessageCallback("getChildren", NewCallback(this, &SlideshowHandler::HandleGetChildren)); web_ui_->RegisterMessageCallback("refreshDirectory", NewCallback(this, &SlideshowHandler::HandleRefreshDirectory)); } void SlideshowHandler::HandleRefreshDirectory(const ListValue* args) { #if defined(OS_CHROMEOS) std::string path = UTF16ToUTF8(ExtractStringValue(args)); GetChildrenForPath(FilePath(path), true); #endif } void SlideshowHandler::GetChildrenForPath(const FilePath& path, bool is_refresh) { filelist_value_.reset(new ListValue()); currentpath_ = path; if (lister_.get()) { lister_->Cancel(); lister_->set_delegate(NULL); lister_ = NULL; } is_refresh_ = is_refresh; if (file_util::EnsureEndsWithSeparator(¤tpath_) && currentpath_.IsAbsolute()) { lister_ = new net::DirectoryLister(currentpath_, this); } else { originalpath_ = currentpath_; currentpath_ = currentpath_.DirName(); lister_ = new net::DirectoryLister(currentpath_, this); } counter_ = 0; currentOffset_ = -1; lister_->Start(); } void SlideshowHandler::HandleGetChildren(const ListValue* args) { #if defined(OS_CHROMEOS) filelist_value_.reset(new ListValue()); std::string path = UTF16ToUTF8(ExtractStringValue(args)); GetChildrenForPath(FilePath(path), false); #endif } bool SlideshowHandler::PathIsImageFile(const char* filename) { #if defined(OS_CHROMEOS) FilePath file = FilePath(filename); std::string ext = file.Extension(); ext = StringToLowerASCII(ext); if (ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".gif") { return true; } else { return false; } #else return false; #endif } void SlideshowHandler::OnListFile( const net::DirectoryLister::DirectoryListerData& data) { #if defined(OS_CHROMEOS) if (data.info.filename[0] == '.') { return; } if (!PathIsImageFile(data.info.filename.c_str())) { return; } DictionaryValue* file_value = new DictionaryValue(); file_value->SetString(kPropertyTitle, data.info.filename); file_value->SetString(kPropertyPath, currentpath_.Append(data.info.filename).value()); file_value->SetBoolean(kPropertyDirectory, S_ISDIR(data.info.stat.st_mode)); filelist_value_->Append(file_value); std::string val; file_value->GetString(kPropertyTitle, &val); if (val == originalpath_.BaseName().value()) { currentOffset_ = counter_; } counter_++; #endif } void SlideshowHandler::OnListDone(int error) { DictionaryValue info_value; counter_ = 0; if (!(file_util::EnsureEndsWithSeparator(&originalpath_) && originalpath_.IsAbsolute()) && currentOffset_ != -1) { info_value.SetInteger(kPropertyOffset, currentOffset_); } if (is_refresh_) { info_value.SetString("functionCall", "refresh"); } else { info_value.SetString("functionCall", "getChildren"); } info_value.SetString(kPropertyPath, currentpath_.value()); web_ui_->CallJavascriptFunction("browseFileResult", info_value, *(filelist_value_.get())); } //////////////////////////////////////////////////////////////////////////////// // // SlideshowUI // //////////////////////////////////////////////////////////////////////////////// SlideshowUI::SlideshowUI(TabContents* contents) : WebUI(contents) { SlideshowHandler* handler = new SlideshowHandler(); AddMessageHandler((handler)->Attach(this)); handler->Init(); SlideshowUIHTMLSource* html_source = new SlideshowUIHTMLSource(); // Set up the chrome://slideshow/ source. contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source); }