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/screenshot_source.h" 6 7#include "base/file_util.h" 8#include "base/memory/ref_counted_memory.h" 9#include "base/path_service.h" 10#include "base/synchronization/waitable_event.h" 11#include "base/task.h" 12#include "chrome/common/chrome_paths.h" 13#include "chrome/common/url_constants.h" 14#include "content/browser/browser_thread.h" 15 16static const char kCurrentScreenshot[] = "current"; 17#if defined(OS_CHROMEOS) 18static const char kSavedScreenshots[] = "saved/"; 19#endif 20 21static const char kScreenshotsRelativePath[] = "/Screenshots/"; 22 23#if defined(OS_CHROMEOS) 24// Read the file from the screenshots directory into the read_bytes vector. 25void ReadScreenshot(const std::string& filename, 26 std::vector<unsigned char>* read_bytes, 27 base::WaitableEvent* read_complete) { 28 read_bytes->clear(); 29 30 FilePath fileshelf_path; 31 if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &fileshelf_path)) { 32 read_complete->Signal(); 33 return; 34 } 35 36 FilePath file(fileshelf_path.value() + std::string(kScreenshotsRelativePath) + 37 filename); 38 39 int64 file_size = 0; 40 if (!file_util::GetFileSize(file, &file_size)) { 41 read_complete->Signal(); 42 return; 43 } 44 45 // expand vector to file size 46 read_bytes->resize(file_size); 47 // read file into the vector 48 int bytes_read = 0; 49 if (!(bytes_read = file_util::ReadFile(file, 50 reinterpret_cast<char*>( 51 &read_bytes->front()), 52 static_cast<int>(file_size)))) 53 read_bytes->clear(); 54 55 // We're done, if successful, read_bytes will have the data 56 // otherwise, it'll be empty. 57 read_complete->Signal(); 58} 59 60// Get a saved screenshot - read on the FILE thread. 61std::vector<unsigned char> GetSavedScreenshot(std::string filename) { 62 base::WaitableEvent read_complete(true, false); 63 std::vector<unsigned char> bytes; 64 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 65 NewRunnableFunction(&ReadScreenshot, filename, 66 &bytes, &read_complete)); 67 read_complete.Wait(); 68 return bytes; 69} 70#endif 71 72std::vector<unsigned char> ScreenshotSource::GetScreenshot( 73 const std::string& full_path) { 74 // Strip the query param value - we only use it as a hack to ensure our 75 // image gets reloaded instead of being pulled from the browser cache 76 std::string path = full_path.substr(0, full_path.find_first_of("?")); 77 if (path == kCurrentScreenshot) { 78 return current_screenshot_; 79#if defined(OS_CHROMEOS) 80 } else if (path.compare(0, strlen(kSavedScreenshots), 81 kSavedScreenshots) == 0) { 82 // Split the saved screenshot filename from the path 83 std::string filename = path.substr(strlen(kSavedScreenshots)); 84 85 return GetSavedScreenshot(filename); 86#endif 87 } else { 88 std::vector<unsigned char> ret; 89 // TODO(rkc): Weird vc bug, return std::vector<unsigned char>() causes 90 // the object assigned to the return value of this function magically 91 // change it's address 0x0; look into this eventually. 92 return ret; 93 } 94} 95 96ScreenshotSource::ScreenshotSource( 97 std::vector<unsigned char>* current_screenshot) 98 : DataSource(chrome::kChromeUIScreenshotPath, MessageLoop::current()) { 99 // Setup the last screenshot taken. 100 if (current_screenshot) 101 current_screenshot_ = *current_screenshot; 102 else 103 current_screenshot_.clear(); 104} 105 106ScreenshotSource::~ScreenshotSource() {} 107 108void ScreenshotSource::StartDataRequest(const std::string& path, 109 bool is_incognito, 110 int request_id) { 111 SendResponse(request_id, new RefCountedBytes(GetScreenshot(path))); 112} 113 114std::string ScreenshotSource::GetMimeType(const std::string&) const { 115 // We need to explicitly return a mime type, otherwise if the user tries to 116 // drag the image they get no extension. 117 return "image/png"; 118} 119