From fdd574cea544ea5608ab9ba56873bcd9bd2c7366 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Tue, 17 Jan 2017 19:53:13 +0530 Subject: [PATCH 01/55] browser: implement pdf renderer as webui --- .gitmodules | 3 + atom/app/atom_content_client.cc | 21 +++ atom/browser/atom_browser_main_parts.cc | 4 + .../atom_resource_dispatcher_host_delegate.cc | 44 +++++ .../atom_resource_dispatcher_host_delegate.h | 7 + .../browser/atom_web_ui_controller_factory.cc | 158 ++++++++++++++++++ atom/browser/atom_web_ui_controller_factory.h | 40 +++++ atom/renderer/atom_renderer_client.cc | 3 + electron.gyp | 31 ++++ filenames.gypi | 8 + lib/renderer/init.js | 2 +- script/create-dist.py | 2 + 12 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 atom/browser/atom_web_ui_controller_factory.cc create mode 100644 atom/browser/atom_web_ui_controller_factory.h diff --git a/.gitmodules b/.gitmodules index 5bc253bad5c..80cafd9bdde 100644 --- a/.gitmodules +++ b/.gitmodules @@ -22,3 +22,6 @@ [submodule "vendor/boto"] path = vendor/boto url = https://github.com/boto/boto.git +[submodule "vendor/grit"] + path = vendor/grit + url = https://chromium.googlesource.com/chromium/src/tools/grit.git diff --git a/atom/app/atom_content_client.cc b/atom/app/atom_content_client.cc index 760a42732b3..f1b7a9c36b9 100644 --- a/atom/app/atom_content_client.cc +++ b/atom/app/atom_content_client.cc @@ -18,6 +18,7 @@ #include "content/public/common/content_constants.h" #include "content/public/common/pepper_plugin_info.h" #include "content/public/common/user_agent.h" +#include "pdf/pdf.h" #include "ppapi/shared_impl/ppapi_permissions.h" #include "third_party/widevine/cdm/stub/widevine_cdm_version.h" #include "ui/base/l10n/l10n_util.h" @@ -108,6 +109,25 @@ content::PepperPluginInfo CreateWidevineCdmInfo(const base::FilePath& path, } #endif +void ComputeBuiltInPlugins(std::vector* plugins) { + content::PepperPluginInfo pdf_info; + pdf_info.is_internal = true; + pdf_info.is_out_of_process = true; + pdf_info.name = "Chromium PDF Viewer"; + pdf_info.description = "Portable Document Format"; + pdf_info.path = base::FilePath::FromUTF8Unsafe("internal-pdf-viewer"); + content::WebPluginMimeType pdf_mime_type("application/x-google-chrome-pdf", + "pdf", "Portable Document Format"); + pdf_info.mime_types.push_back(pdf_mime_type); + pdf_info.internal_entry_points.get_interface = chrome_pdf::PPP_GetInterface; + pdf_info.internal_entry_points.initialize_module = + chrome_pdf::PPP_InitializeModule; + pdf_info.internal_entry_points.shutdown_module = + chrome_pdf::PPP_ShutdownModule; + pdf_info.permissions = ppapi::PERMISSION_PRIVATE | ppapi::PERMISSION_DEV; + plugins->push_back(pdf_info); +} + void ConvertStringWithSeparatorToVector(std::vector* vec, const char* separator, const char* cmd_switch) { @@ -190,6 +210,7 @@ void AtomContentClient::AddPepperPlugins( #if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS) AddWidevineCdmFromCommandLine(plugins); #endif + ComputeBuiltInPlugins(plugins); } void AtomContentClient::AddServiceWorkerSchemes( diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index 4031fb27cf3..eb09b18b71f 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -12,6 +12,7 @@ #include "atom/browser/browser.h" #include "atom/browser/javascript_environment.h" #include "atom/browser/node_debugger.h" +#include "atom/browser/atom_web_ui_controller_factory.h" #include "atom/common/api/atom_bindings.h" #include "atom/common/node_bindings.h" #include "atom/common/node_includes.h" @@ -166,6 +167,9 @@ void AtomBrowserMainParts::PreMainMessageLoopRun() { base::Bind(&v8::Isolate::LowMemoryNotification, base::Unretained(js_env_->isolate()))); + content::WebUIControllerFactory::RegisterFactory( + AtomWebUIControllerFactory::GetInstance()); + brightray::BrowserMainParts::PreMainMessageLoopRun(); bridge_task_runner_->MessageLoopIsReady(); bridge_task_runner_ = nullptr; diff --git a/atom/browser/atom_resource_dispatcher_host_delegate.cc b/atom/browser/atom_resource_dispatcher_host_delegate.cc index 78589112c55..1438c220b0a 100644 --- a/atom/browser/atom_resource_dispatcher_host_delegate.cc +++ b/atom/browser/atom_resource_dispatcher_host_delegate.cc @@ -9,8 +9,11 @@ #include "atom/common/platform_util.h" #include "base/strings/utf_string_conversions.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/stream_handle.h" +#include "content/public/browser/stream_info.h" #include "net/base/escape.h" #include "net/ssl/client_cert_store.h" +#include "net/url_request/url_request.h" #include "url/gurl.h" #if defined(USE_NSS_CERTS) @@ -57,6 +60,22 @@ void HandleExternalProtocolInUI( permission_helper->RequestOpenExternalPermission(callback, has_user_gesture); } +void OnPdfStreamCreated(std::unique_ptr stream, + int64_t expected_content_size, + const content::ResourceRequestInfo::WebContentsGetter& + web_contents_getter) { + content::WebContents* web_contents = web_contents_getter.Run(); + if (!web_contents) + return; + + LOG(WARNING) << stream->handle->GetURL(); + LOG(WARNING) << stream->original_url; + + content::NavigationController::LoadURLParams params( + GURL("chrome://pdf-viewer/index.html")); + web_contents->GetController().LoadURLWithParams(params); +} + } // namespace AtomResourceDispatcherHostDelegate::AtomResourceDispatcherHostDelegate() { @@ -95,4 +114,29 @@ AtomResourceDispatcherHostDelegate::CreateClientCertStore( #endif } +bool AtomResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream( + net::URLRequest* request, + const base::FilePath& plugin_path, + const std::string& mime_type, + GURL* origin, + std::string* payload) { + if (mime_type == "application/pdf") { + *origin = GURL("chrome://pdf-viewer/"); + return true; + } + return false; +} + +void AtomResourceDispatcherHostDelegate::OnStreamCreated( + net::URLRequest* request, + std::unique_ptr stream) { + const content::ResourceRequestInfo* info = + content::ResourceRequestInfo::ForRequest(request); + content::BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&OnPdfStreamCreated, base::Passed(&stream), + request->GetExpectedContentSize(), + info->GetWebContentsGetterForRequest())); +} + } // namespace atom diff --git a/atom/browser/atom_resource_dispatcher_host_delegate.h b/atom/browser/atom_resource_dispatcher_host_delegate.h index 681fec6f6fb..2a5ca1edd0a 100644 --- a/atom/browser/atom_resource_dispatcher_host_delegate.h +++ b/atom/browser/atom_resource_dispatcher_host_delegate.h @@ -22,6 +22,13 @@ class AtomResourceDispatcherHostDelegate net::URLRequest* request) override; std::unique_ptr CreateClientCertStore( content::ResourceContext* resource_context) override; + bool ShouldInterceptResourceAsStream(net::URLRequest* request, + const base::FilePath& plugin_path, + const std::string& mime_type, + GURL* origin, + std::string* payload) override; + void OnStreamCreated(net::URLRequest* request, + std::unique_ptr stream) override; }; } // namespace atom diff --git a/atom/browser/atom_web_ui_controller_factory.cc b/atom/browser/atom_web_ui_controller_factory.cc new file mode 100644 index 00000000000..3682309a71a --- /dev/null +++ b/atom/browser/atom_web_ui_controller_factory.cc @@ -0,0 +1,158 @@ +// Copyright (c) 2017 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/atom_web_ui_controller_factory.h" + +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/url_data_source.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_controller.h" +#include "content/public/common/bindings_policy.h" +#include "grit/pdf_viewer_resources_map.h" +#include "ui/base/resource/resource_bundle.h" + +namespace atom { + +namespace { + +const char kChromeUIPdfViewerHost[] = "pdf-viewer"; + +std::string PathWithoutParams(const std::string& path) { + return GURL(std::string("chrome://pdf-viewer/") + path).path().substr(1); +} + +std::string GetMimeTypeForPath(const std::string& path) { + std::string filename = PathWithoutParams(path); + if (base::EndsWith(filename, ".html", base::CompareCase::INSENSITIVE_ASCII)) { + return "text/html"; + } else if (base::EndsWith(filename, ".css", + base::CompareCase::INSENSITIVE_ASCII)) { + return "text/css"; + } else if (base::EndsWith(filename, ".js", + base::CompareCase::INSENSITIVE_ASCII)) { + return "application/javascript"; + } else if (base::EndsWith(filename, ".png", + base::CompareCase::INSENSITIVE_ASCII)) { + return "image/png"; + } else if (base::EndsWith(filename, ".gif", + base::CompareCase::INSENSITIVE_ASCII)) { + return "image/gif"; + } else if (base::EndsWith(filename, ".svg", + base::CompareCase::INSENSITIVE_ASCII)) { + return "image/svg+xml"; + } else if (base::EndsWith(filename, ".manifest", + base::CompareCase::INSENSITIVE_ASCII)) { + return "text/cache-manifest"; + } + return "text/html"; +} + +class BundledDataSource : public content::URLDataSource { + public: + BundledDataSource() { + for (size_t i = 0; i < kPdfViewerResourcesSize; ++i) { + base::FilePath resource_path = + base::FilePath().AppendASCII(kPdfViewerResources[i].name); + resource_path = resource_path.NormalizePathSeparators(); + + DCHECK(path_to_resource_id_.find(resource_path) == + path_to_resource_id_.end()); + path_to_resource_id_[resource_path] = kPdfViewerResources[i].value; + } + } + + // content::URLDataSource implementation. + std::string GetSource() const override { return kChromeUIPdfViewerHost; } + + void StartDataRequest(const std::string& path, + int render_process_id, + int render_frame_id, + const GotDataCallback& callback) override { + std::string filename = PathWithoutParams(path); + std::map::const_iterator entry = + path_to_resource_id_.find(base::FilePath(filename)); + if (entry != path_to_resource_id_.end()) { + int resource_id = entry->second; + const ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); + callback.Run(rb.LoadDataResourceBytes(resource_id)); + } + } + + std::string GetMimeType(const std::string& path) const override { + return GetMimeTypeForPath(path); + } + + bool ShouldAddContentSecurityPolicy() const override { return false; } + + bool ShouldDenyXFrameOptions() const override { return false; } + + bool ShouldServeMimeTypeAsContentTypeHeader() const override { return true; } + + private: + ~BundledDataSource() override {} + + // A map from a resource path to the resource ID. + std::map path_to_resource_id_; + + DISALLOW_COPY_AND_ASSIGN(BundledDataSource); +}; + +class PdfViewerUI : public content::WebUIController { + public: + PdfViewerUI(content::BrowserContext* browser_context, content::WebUI* web_ui) + : content::WebUIController(web_ui) { + content::URLDataSource::Add(browser_context, new BundledDataSource); + } + + void RenderViewCreated(content::RenderViewHost* rvh) override { + rvh->AllowBindings(content::BINDINGS_POLICY_WEB_UI); + } +}; +} + +// static +AtomWebUIControllerFactory* AtomWebUIControllerFactory::GetInstance() { + return base::Singleton::get(); +} + +AtomWebUIControllerFactory::AtomWebUIControllerFactory() {} + +AtomWebUIControllerFactory::~AtomWebUIControllerFactory() {} + +content::WebUI::TypeID AtomWebUIControllerFactory::GetWebUIType( + content::BrowserContext* browser_context, + const GURL& url) const { + if (url.host() == kChromeUIPdfViewerHost) { + return const_cast(this); + } + + return content::WebUI::kNoWebUI; +} + +bool AtomWebUIControllerFactory::UseWebUIForURL( + content::BrowserContext* browser_context, + const GURL& url) const { + return GetWebUIType(browser_context, url) != content::WebUI::kNoWebUI; +} + +bool AtomWebUIControllerFactory::UseWebUIBindingsForURL( + content::BrowserContext* browser_context, + const GURL& url) const { + return UseWebUIForURL(browser_context, url); +} + +content::WebUIController* +AtomWebUIControllerFactory::CreateWebUIControllerForURL(content::WebUI* web_ui, + const GURL& url) const { + if (url.host() == kChromeUIPdfViewerHost) { + auto browser_context = web_ui->GetWebContents()->GetBrowserContext(); + return new PdfViewerUI(browser_context, web_ui); + } + return nullptr; +} + +} // namespace atom diff --git a/atom/browser/atom_web_ui_controller_factory.h b/atom/browser/atom_web_ui_controller_factory.h new file mode 100644 index 00000000000..d63aa0eceea --- /dev/null +++ b/atom/browser/atom_web_ui_controller_factory.h @@ -0,0 +1,40 @@ +// Copyright (c) 2017 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_ATOM_WEB_UI_CONTROLLER_FACTORY_H_ +#define ATOM_BROWSER_ATOM_WEB_UI_CONTROLLER_FACTORY_H_ + +#include "base/macros.h" +#include "base/memory/singleton.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_controller_factory.h" + +namespace atom { + +class AtomWebUIControllerFactory : public content::WebUIControllerFactory { + public: + static AtomWebUIControllerFactory* GetInstance(); + + AtomWebUIControllerFactory(); + virtual ~AtomWebUIControllerFactory(); + + content::WebUI::TypeID GetWebUIType(content::BrowserContext* browser_context, + const GURL& url) const override; + bool UseWebUIForURL(content::BrowserContext* browser_context, + const GURL& url) const override; + bool UseWebUIBindingsForURL(content::BrowserContext* browser_context, + const GURL& url) const override; + content::WebUIController* CreateWebUIControllerForURL( + content::WebUI* web_ui, + const GURL& url) const override; + + private: + friend struct base::DefaultSingletonTraits; + + DISALLOW_COPY_AND_ASSIGN(AtomWebUIControllerFactory); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_ATOM_WEB_UI_CONTROLLER_FACTORY_H_ diff --git a/atom/renderer/atom_renderer_client.cc b/atom/renderer/atom_renderer_client.cc index 637792c2aed..1db52bd7cbc 100644 --- a/atom/renderer/atom_renderer_client.cc +++ b/atom/renderer/atom_renderer_client.cc @@ -274,6 +274,9 @@ void AtomRendererClient::RenderFrameCreated( // This is required for widevine plugin detection provided during runtime. blink::resetPluginCache(); + blink::WebSecurityPolicy::addOriginAccessWhitelistEntry( + GURL("chrome://pdf-viewer/"), "file", "", true); + // Parse --secure-schemes=scheme1,scheme2 std::vector secure_schemes_list = ParseSchemesCLISwitch(switches::kSecureSchemes); diff --git a/electron.gyp b/electron.gyp index 47bc67b98e6..9a47100008c 100644 --- a/electron.gyp +++ b/electron.gyp @@ -6,6 +6,7 @@ 'company_abbr%': 'github', 'version%': '1.6.3', 'js2c_input_dir': '<(SHARED_INTERMEDIATE_DIR)/js2c', + 'grit_dir': 'vendor/grit', }, 'includes': [ 'filenames.gypi', @@ -210,6 +211,7 @@ 'type': 'static_library', 'dependencies': [ 'atom_js2c', + 'pdfviewer', 'vendor/brightray/brightray.gyp:brightray', 'vendor/node/node.gyp:node', ], @@ -417,6 +419,34 @@ } ], }, # target app2asar + { + 'target_name': 'pdfviewer', + 'type': 'none', + 'actions': [ + { + 'action_name': 'pdfviewer', + 'inputs': [ + '<(grit_dir)/grit.py', + '<@(pdf_viewer_sources)', + ], + 'outputs': [ + 'pdf_viewer_resouces.h', + 'pdf_viewer_resouces_map.cc', + 'pdf_viewer_resouces_map.h', + 'pdf_viewer_resources.pak', + ], + 'action': [ + 'python', + '<(grit_dir)/grit.py', + '-i', + '<@(pdf_viewer_sources)', + 'build', + '-o', + '<(SHARED_INTERMEDIATE_DIR)/grit', + ], + } + ], + }, # target pdfviewer { 'target_name': 'atom_js2c_copy', 'type': 'none', @@ -543,6 +573,7 @@ '<(libchromiumcontent_dir)/icudtl.dat', '<(libchromiumcontent_dir)/natives_blob.bin', '<(libchromiumcontent_dir)/snapshot_blob.bin', + '<(PRODUCT_DIR)/pdf_viewer_resources.pak', ], 'xcode_settings': { 'ATOM_BUNDLE_ID': 'com.<(company_abbr).<(project_name).framework', diff --git a/filenames.gypi b/filenames.gypi index 44a6fbfc431..3c7e4d21729 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -96,6 +96,9 @@ 'default_app/main.js', 'default_app/package.json', ], + 'pdf_viewer_sources': [ + 'atom/browser/resources/pdf_viewer/resources.grd', + ], 'lib_sources': [ 'atom/app/atom_content_client.cc', 'atom/app/atom_content_client.h', @@ -195,6 +198,8 @@ 'atom/browser/atom_resource_dispatcher_host_delegate.h', 'atom/browser/atom_speech_recognition_manager_delegate.cc', 'atom/browser/atom_speech_recognition_manager_delegate.h', + 'atom/browser/atom_web_ui_controller_factory.cc', + 'atom/browser/atom_web_ui_controller_factory.h', 'atom/browser/bridge_task_runner.cc', 'atom/browser/bridge_task_runner.h', 'atom/browser/browser.cc', @@ -617,6 +622,9 @@ 'chromium_src/net/test/embedded_test_server/tcp_listen_socket.h', '<@(native_mate_files)', '<(SHARED_INTERMEDIATE_DIR)/atom_natives.h', + '<(SHARED_INTERMEDIATE_DIR)/grit/pdf_viewer_resources.h', + '<(SHARED_INTERMEDIATE_DIR)/grit/pdf_viewer_resources_map.cc', + '<(SHARED_INTERMEDIATE_DIR)/grit/pdf_viewer_resources_map.h', ], 'lib_sources_linux': [ 'chromium_src/chrome/browser/icon_loader_auralinux.cc', diff --git a/lib/renderer/init.js b/lib/renderer/init.js index 24e19b9d2a6..7bd707c102e 100644 --- a/lib/renderer/init.js +++ b/lib/renderer/init.js @@ -76,7 +76,7 @@ if (window.location.protocol === 'chrome-devtools:') { // Override some inspector APIs. require('./inspector') nodeIntegration = 'true' -} else if (window.location.protocol === 'chrome-extension:') { +} else if (window.location.protocol === 'chrome-extension:' || window.location.protocol === 'chrome:') { // Add implementations of chrome API. require('./chrome-api').injectTo(window.location.hostname, isBackgroundPage, window) nodeIntegration = 'false' diff --git a/script/create-dist.py b/script/create-dist.py index 5a63b20707d..35a109cfa3f 100755 --- a/script/create-dist.py +++ b/script/create-dist.py @@ -31,6 +31,7 @@ TARGET_BINARIES = { 'win32': [ '{0}.exe'.format(PROJECT_NAME), # 'electron.exe' 'content_shell.pak', + 'pdf_viewer_resources.pak', 'd3dcompiler_47.dll', 'icudtl.dat', 'libEGL.dll', @@ -48,6 +49,7 @@ TARGET_BINARIES = { 'linux': [ PROJECT_NAME, # 'electron' 'content_shell.pak', + 'pdf_viewer_resources.pak', 'icudtl.dat', 'libffmpeg.so', 'libnode.so', From be480fb634fe01b74af7a68f18c2b838108b9c0c Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Tue, 17 Jan 2017 19:57:16 +0530 Subject: [PATCH 02/55] import pdf ui --- .../resources/pdf_viewer/browser_api.js | 204 ++++ .../resources/pdf_viewer/elements/icons.html | 19 + .../pdf_viewer/elements/shared-icon-style.css | 15 + .../viewer-bookmark/viewer-bookmark.css | 52 + .../viewer-bookmark/viewer-bookmark.html | 26 + .../viewer-bookmark/viewer-bookmark.js | 92 ++ .../viewer-bookmarks-content.html | 11 + .../viewer-bookmarks-content.js | 7 + .../viewer-error-screen.css | 7 + .../viewer-error-screen.html | 22 + .../viewer-error-screen.js | 35 + .../viewer-page-indicator.css | 35 + .../viewer-page-indicator.html | 10 + .../viewer-page-indicator.js | 64 ++ .../viewer-page-selector.css | 52 + .../viewer-page-selector.html | 19 + .../viewer-page-selector.js | 59 ++ .../viewer-password-screen.html | 30 + .../viewer-password-screen.js | 57 ++ .../viewer-pdf-toolbar/viewer-pdf-toolbar.css | 92 ++ .../viewer-pdf-toolbar.html | 68 ++ .../viewer-pdf-toolbar/viewer-pdf-toolbar.js | 146 +++ .../viewer-toolbar-dropdown.css | 59 ++ .../viewer-toolbar-dropdown.html | 29 + .../viewer-toolbar-dropdown.js | 138 +++ .../viewer-zoom-button.css | 32 + .../viewer-zoom-button.html | 15 + .../viewer-zoom-toolbar/viewer-zoom-button.js | 95 ++ .../viewer-zoom-toolbar.css | 41 + .../viewer-zoom-toolbar.html | 21 + .../viewer-zoom-toolbar.js | 75 ++ atom/browser/resources/pdf_viewer/index.css | 50 + atom/browser/resources/pdf_viewer/index.html | 42 + atom/browser/resources/pdf_viewer/main.js | 55 ++ .../browser/resources/pdf_viewer/navigator.js | 211 +++++ atom/browser/resources/pdf_viewer/ods-cpp.pdf | Bin 0 -> 1519810 bytes .../pdf_viewer/open_pdf_params_parser.js | 147 +++ atom/browser/resources/pdf_viewer/pdf.js | 889 ++++++++++++++++++ .../resources/pdf_viewer/pdf_scripting_api.js | 262 ++++++ .../resources/pdf_viewer/resources.grd | 59 ++ .../resources/pdf_viewer/toolbar_manager.js | 252 +++++ atom/browser/resources/pdf_viewer/viewport.js | 599 ++++++++++++ .../resources/pdf_viewer/viewport_scroller.js | 135 +++ .../resources/pdf_viewer/zoom_manager.js | 83 ++ 44 files changed, 4411 insertions(+) create mode 100644 atom/browser/resources/pdf_viewer/browser_api.js create mode 100644 atom/browser/resources/pdf_viewer/elements/icons.html create mode 100644 atom/browser/resources/pdf_viewer/elements/shared-icon-style.css create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-bookmark/viewer-bookmark.css create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-bookmark/viewer-bookmark.html create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-bookmark/viewer-bookmark.js create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-bookmarks-content/viewer-bookmarks-content.html create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-bookmarks-content/viewer-bookmarks-content.js create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-error-screen/viewer-error-screen.css create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-error-screen/viewer-error-screen.html create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-error-screen/viewer-error-screen.js create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-page-indicator/viewer-page-indicator.css create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-page-indicator/viewer-page-indicator.html create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-page-indicator/viewer-page-indicator.js create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-page-selector/viewer-page-selector.css create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-page-selector/viewer-page-selector.html create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-page-selector/viewer-page-selector.js create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-password-screen/viewer-password-screen.html create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-password-screen/viewer-password-screen.js create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.css create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.js create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.css create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.js create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-button.css create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-button.html create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-button.js create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.css create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.html create mode 100644 atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.js create mode 100644 atom/browser/resources/pdf_viewer/index.css create mode 100644 atom/browser/resources/pdf_viewer/index.html create mode 100644 atom/browser/resources/pdf_viewer/main.js create mode 100644 atom/browser/resources/pdf_viewer/navigator.js create mode 100644 atom/browser/resources/pdf_viewer/ods-cpp.pdf create mode 100644 atom/browser/resources/pdf_viewer/open_pdf_params_parser.js create mode 100644 atom/browser/resources/pdf_viewer/pdf.js create mode 100644 atom/browser/resources/pdf_viewer/pdf_scripting_api.js create mode 100644 atom/browser/resources/pdf_viewer/resources.grd create mode 100644 atom/browser/resources/pdf_viewer/toolbar_manager.js create mode 100644 atom/browser/resources/pdf_viewer/viewport.js create mode 100644 atom/browser/resources/pdf_viewer/viewport_scroller.js create mode 100644 atom/browser/resources/pdf_viewer/zoom_manager.js diff --git a/atom/browser/resources/pdf_viewer/browser_api.js b/atom/browser/resources/pdf_viewer/browser_api.js new file mode 100644 index 00000000000..e4bcf2388ff --- /dev/null +++ b/atom/browser/resources/pdf_viewer/browser_api.js @@ -0,0 +1,204 @@ +// Copyright 2015 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. + +'use strict'; + +/** + * Returns a promise that will resolve to the default zoom factor. + * @param {!Object} streamInfo The stream object pointing to the data contained + * in the PDF. + * @return {Promise} A promise that will resolve to the default zoom + * factor. + */ +function lookupDefaultZoom(streamInfo) { + // Webviews don't run in tabs so |streamInfo.tabId| is -1 when running within + // a webview. + if (!chrome.tabs || streamInfo.tabId < 0) + return Promise.resolve(1); + + return new Promise(function(resolve, reject) { + chrome.tabs.getZoomSettings(streamInfo.tabId, function(zoomSettings) { + resolve(zoomSettings.defaultZoomFactor); + }); + }); +} + +/** + * Returns a promise that will resolve to the initial zoom factor + * upon starting the plugin. This may differ from the default zoom + * if, for example, the page is zoomed before the plugin is run. + * @param {!Object} streamInfo The stream object pointing to the data contained + * in the PDF. + * @return {Promise} A promise that will resolve to the initial zoom + * factor. + */ +function lookupInitialZoom(streamInfo) { + // Webviews don't run in tabs so |streamInfo.tabId| is -1 when running within + // a webview. + if (!chrome.tabs || streamInfo.tabId < 0) + return Promise.resolve(1); + + return new Promise(function(resolve, reject) { + chrome.tabs.getZoom(streamInfo.tabId, resolve); + }); +} + +/** + * A class providing an interface to the browser. + */ +class BrowserApi { + /** + * @constructor + * @param {!Object} streamInfo The stream object which points to the data + * contained in the PDF. + * @param {number} defaultZoom The default browser zoom. + * @param {number} initialZoom The initial browser zoom + * upon starting the plugin. + * @param {boolean} manageZoom Whether to manage zoom. + */ + constructor(streamInfo, defaultZoom, initialZoom, manageZoom) { + this.streamInfo_ = streamInfo; + this.defaultZoom_ = defaultZoom; + this.initialZoom_ = initialZoom; + this.manageZoom_ = manageZoom; + } + + /** + * Returns a promise to a BrowserApi. + * @param {!Object} streamInfo The stream object pointing to the data + * contained in the PDF. + * @param {boolean} manageZoom Whether to manage zoom. + */ + static create(streamInfo, manageZoom) { + /*return Promise.all([ + lookupDefaultZoom(streamInfo), + lookupInitialZoom(streamInfo) + ]).then(function(zoomFactors) {*/ + return new BrowserApi( + streamInfo, 1.0, 1.0, manageZoom); + //}); + } + + /** + * Returns the stream info pointing to the data contained in the PDF. + * @return {Object} The stream info object. + */ + getStreamInfo() { + return this.streamInfo_; + } + + /** + * Aborts the stream. + */ + abortStream() { + if (chrome.mimeHandlerPrivate) + chrome.mimeHandlerPrivate.abortStream(); + } + + /** + * Sets the browser zoom. + * @param {number} zoom The zoom factor to send to the browser. + * @return {Promise} A promise that will be resolved when the browser zoom + * has been updated. + */ + setZoom(zoom) { + if (!this.manageZoom_) + return Promise.resolve(); + return new Promise(function(resolve, reject) { + chrome.tabs.setZoom(this.streamInfo_.tabId, zoom, resolve); + }.bind(this)); + } + + /** + * Returns the default browser zoom factor. + * @return {number} The default browser zoom factor. + */ + getDefaultZoom() { + return this.defaultZoom_; + } + + /** + * Returns the initial browser zoom factor. + * @return {number} The initial browser zoom factor. + */ + getInitialZoom() { + return this.initialZoom_; + } + + /** + * Adds an event listener to be notified when the browser zoom changes. + * @param {function} listener The listener to be called with the new zoom + * factor. + */ + addZoomEventListener(listener) { + if (!this.manageZoom_) + return; + + chrome.tabs.onZoomChange.addListener(function(zoomChangeInfo) { + if (zoomChangeInfo.tabId != this.streamInfo_.tabId) + return; + listener(zoomChangeInfo.newZoomFactor); + }.bind(this)); + } +}; + +/** + * Creates a BrowserApi for an extension running as a mime handler. + * @return {Promise} A promise to a BrowserApi instance constructed + * using the mimeHandlerPrivate API. + */ +function createBrowserApiForMimeHandlerView() { + return new Promise(function(resolve, reject) { + chrome.mimeHandlerPrivate.getStreamInfo(resolve); + }).then(function(streamInfo) { + let manageZoom = !streamInfo.embedded && streamInfo.tabId != -1; + return new Promise(function(resolve, reject) { + if (!manageZoom) { + resolve(); + return; + } + chrome.tabs.setZoomSettings( + streamInfo.tabId, {mode: 'manual', scope: 'per-tab'}, resolve); + }).then(function() { return BrowserApi.create(streamInfo, manageZoom); }); + }); +} + +/** + * Creates a BrowserApi instance for an extension not running as a mime handler. + * @return {Promise} A promise to a BrowserApi instance constructed + * from the URL. + */ +function createBrowserApi(streamURL, originalURL) { + //let url = window.location.search.substring(1); + let streamInfo = { + streamUrl: streamURL, + originalUrl: originalURL, + responseHeaders: {}, + embedded: window.parent != window, + tabId: -1, + }; + return new Promise(function(resolve, reject) { + if (!chrome.tabs) { + resolve(); + return; + } + //chrome.tabs.getCurrent(function(tab) { + streamInfo.tabId = -1; + resolve(); + //}); + }).then(function() { return BrowserApi.create(streamInfo, false); }); +} + +/** + * Returns a promise that will resolve to a BrowserApi instance. + * @return {Promise} A promise to a BrowserApi instance for the + * current environment. + +function createBrowserApi(streamURL, originalURL) { + //if (window.location.search) + return createBrowserApiForStandaloneExtension(); + + //return createBrowserApiForMimeHandlerView(); +} +*/ diff --git a/atom/browser/resources/pdf_viewer/elements/icons.html b/atom/browser/resources/pdf_viewer/elements/icons.html new file mode 100644 index 00000000000..3442301b929 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/icons.html @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + diff --git a/atom/browser/resources/pdf_viewer/elements/shared-icon-style.css b/atom/browser/resources/pdf_viewer/elements/shared-icon-style.css new file mode 100644 index 00000000000..59037556c74 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/shared-icon-style.css @@ -0,0 +1,15 @@ +/* Copyright 2015 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. */ + +:root { + --iron-icon-height: 20px; + --iron-icon-width: 20px; + --paper-icon-button: { + height: 32px; + padding: 6px; + width: 32px; + }; + --paper-icon-button-ink-color: rgb(189, 189, 189); + --viewer-icon-ink-color: rgb(189, 189, 189); +} diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-bookmark/viewer-bookmark.css b/atom/browser/resources/pdf_viewer/elements/viewer-bookmark/viewer-bookmark.css new file mode 100644 index 00000000000..74ac2728bd5 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-bookmark/viewer-bookmark.css @@ -0,0 +1,52 @@ +/* Copyright 2015 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. */ + +#item { + @apply(--layout-center); + @apply(--layout-horizontal); + color: rgb(80, 80, 80); + cursor: pointer; + font-size: 77.8%; + height: 30px; + position: relative; +} + +#item:hover { + background-color: rgb(237, 237, 237); + color: rgb(20, 20, 20); +} + +paper-ripple { + /* Allowing the ripple to capture pointer events prevents a focus rectangle + * for showing up for clicks, while still allowing it with tab-navigation. + * This undoes a paper-ripple bugfix aimed at non-Chrome browsers. + * TODO(tsergeant): Improve focus in viewer-bookmark so this can be removed + * (https://crbug.com/5448190). */ + pointer-events: auto; +} + +#title { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +#expand { + --iron-icon-height: 16px; + --iron-icon-width: 16px; + --paper-icon-button-ink-color: var(--paper-grey-900); + height: 28px; + min-width: 28px; + padding: 6px; + transition: transform 150ms; + width: 28px; +} + +:host-context([dir=rtl]) #expand { + transform: rotate(180deg); +} + +:host([children-shown]) #expand { + transform: rotate(90deg); +} diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-bookmark/viewer-bookmark.html b/atom/browser/resources/pdf_viewer/elements/viewer-bookmark/viewer-bookmark.html new file mode 100644 index 00000000000..0228cb835ff --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-bookmark/viewer-bookmark.html @@ -0,0 +1,26 @@ + + + + + + + + + + diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-bookmark/viewer-bookmark.js b/atom/browser/resources/pdf_viewer/elements/viewer-bookmark/viewer-bookmark.js new file mode 100644 index 00000000000..9d6399070e7 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-bookmark/viewer-bookmark.js @@ -0,0 +1,92 @@ +// Copyright 2015 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. + +(function() { + /** Amount that each level of bookmarks is indented by (px). */ + var BOOKMARK_INDENT = 20; + + Polymer({ + is: 'viewer-bookmark', + + properties: { + /** + * A bookmark object, each containing a: + * - title + * - page (optional) + * - children (an array of bookmarks) + */ + bookmark: { + type: Object, + observer: 'bookmarkChanged_' + }, + + depth: { + type: Number, + observer: 'depthChanged' + }, + + childDepth: Number, + + childrenShown: { + type: Boolean, + reflectToAttribute: true, + value: false + }, + + keyEventTarget: { + type: Object, + value: function() { + return this.$.item; + } + } + }, + + behaviors: [ + Polymer.IronA11yKeysBehavior + ], + + keyBindings: { + 'enter': 'onEnter_', + 'space': 'onSpace_' + }, + + bookmarkChanged_: function() { + this.$.expand.style.visibility = + this.bookmark.children.length > 0 ? 'visible' : 'hidden'; + }, + + depthChanged: function() { + this.childDepth = this.depth + 1; + this.$.item.style.webkitPaddingStart = + (this.depth * BOOKMARK_INDENT) + 'px'; + }, + + onClick: function() { + if (this.bookmark.hasOwnProperty('page')) + this.fire('change-page', {page: this.bookmark.page}); + else if (this.bookmark.hasOwnProperty('uri')) + this.fire('navigate', {uri: this.bookmark.uri, newtab: true}); + }, + + onEnter_: function(e) { + // Don't allow events which have propagated up from the expand button to + // trigger a click. + if (e.detail.keyboardEvent.target != this.$.expand) + this.onClick(); + }, + + onSpace_: function(e) { + // paper-icon-button stops propagation of space events, so there's no need + // to check the event source here. + this.onClick(); + // Prevent default space scroll behavior. + e.detail.keyboardEvent.preventDefault(); + }, + + toggleChildren: function(e) { + this.childrenShown = !this.childrenShown; + e.stopPropagation(); // Prevent the above onClick handler from firing. + } + }); +})(); diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-bookmarks-content/viewer-bookmarks-content.html b/atom/browser/resources/pdf_viewer/elements/viewer-bookmarks-content/viewer-bookmarks-content.html new file mode 100644 index 00000000000..f6bfcafe557 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-bookmarks-content/viewer-bookmarks-content.html @@ -0,0 +1,11 @@ + + + + + + + diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-bookmarks-content/viewer-bookmarks-content.js b/atom/browser/resources/pdf_viewer/elements/viewer-bookmarks-content/viewer-bookmarks-content.js new file mode 100644 index 00000000000..1aa2b5cc232 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-bookmarks-content/viewer-bookmarks-content.js @@ -0,0 +1,7 @@ +// Copyright 2015 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. + +Polymer({ + is: 'viewer-bookmarks-content' +}); diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-error-screen/viewer-error-screen.css b/atom/browser/resources/pdf_viewer/elements/viewer-error-screen/viewer-error-screen.css new file mode 100644 index 00000000000..e1e91bd9b39 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-error-screen/viewer-error-screen.css @@ -0,0 +1,7 @@ +/* Copyright 2015 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. */ + +.last-item { + margin-bottom: 24px; +} diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-error-screen/viewer-error-screen.html b/atom/browser/resources/pdf_viewer/elements/viewer-error-screen/viewer-error-screen.html new file mode 100644 index 00000000000..cdadea281b5 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-error-screen/viewer-error-screen.html @@ -0,0 +1,22 @@ + + + + + + + + + + diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-error-screen/viewer-error-screen.js b/atom/browser/resources/pdf_viewer/elements/viewer-error-screen/viewer-error-screen.js new file mode 100644 index 00000000000..4e461b6ad02 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-error-screen/viewer-error-screen.js @@ -0,0 +1,35 @@ +// Copyright 2014 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. + +Polymer({ + is: 'viewer-error-screen', + properties: { + reloadFn: { + type: Object, + value: null, + observer: 'reloadFnChanged_' + }, + + strings: Object, + }, + + reloadFnChanged_: function() { + // The default margins in paper-dialog don't work well with hiding/showing + // the .buttons div. We need to manually manage the bottom margin to get + // around this. + if (this.reloadFn) + this.$['load-failed-message'].classList.remove('last-item'); + else + this.$['load-failed-message'].classList.add('last-item'); + }, + + show: function() { + this.$.dialog.open(); + }, + + reload: function() { + if (this.reloadFn) + this.reloadFn(); + } +}); diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-page-indicator/viewer-page-indicator.css b/atom/browser/resources/pdf_viewer/elements/viewer-page-indicator/viewer-page-indicator.css new file mode 100644 index 00000000000..ec90ec99f53 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-page-indicator/viewer-page-indicator.css @@ -0,0 +1,35 @@ +/* Copyright 2013 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. */ + +:host { + -webkit-transition: opacity 400ms ease-in-out; + pointer-events: none; + position: fixed; + right: 0; +} + +#text { + background-color: rgba(0, 0, 0, 0.5); + border-radius: 5px; + color: white; + float: left; + font-family: sans-serif; + font-size: 12px; + font-weight: bold; + line-height: 48px; + text-align: center; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8); + width: 62px; +} + +#triangle-right { + border-bottom: 6px solid transparent; + border-left: 8px solid rgba(0, 0, 0, 0.5); + border-top: 6px solid transparent; + display: inline; + float: left; + height: 0; + margin-top: 18px; + width: 0; +} \ No newline at end of file diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-page-indicator/viewer-page-indicator.html b/atom/browser/resources/pdf_viewer/elements/viewer-page-indicator/viewer-page-indicator.html new file mode 100644 index 00000000000..970e0a6a4ba --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-page-indicator/viewer-page-indicator.html @@ -0,0 +1,10 @@ + + + + + + + diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-page-indicator/viewer-page-indicator.js b/atom/browser/resources/pdf_viewer/elements/viewer-page-indicator/viewer-page-indicator.js new file mode 100644 index 00000000000..2cf279b68b1 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-page-indicator/viewer-page-indicator.js @@ -0,0 +1,64 @@ +// Copyright 2014 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. + +Polymer({ + is: 'viewer-page-indicator', + + properties: { + label: { + type: String, + value: '1' + }, + + index: { + type: Number, + observer: 'indexChanged' + }, + + pageLabels: { + type: Array, + value: null, + observer: 'pageLabelsChanged' + } + }, + + timerId: undefined, + + ready: function() { + var callback = this.fadeIn.bind(this, 2000); + window.addEventListener('scroll', function() { + requestAnimationFrame(callback); + }); + }, + + initialFadeIn: function() { + this.fadeIn(6000); + }, + + fadeIn: function(displayTime) { + var percent = window.scrollY / + (document.body.scrollHeight - + document.documentElement.clientHeight); + this.style.top = percent * + (document.documentElement.clientHeight - this.offsetHeight) + 'px'; + this.style.opacity = 1; + clearTimeout(this.timerId); + + this.timerId = setTimeout(function() { + this.style.opacity = 0; + this.timerId = undefined; + }.bind(this), displayTime); + }, + + pageLabelsChanged: function() { + this.indexChanged(); + }, + + indexChanged: function() { + if (this.pageLabels) + this.label = this.pageLabels[this.index]; + else + this.label = String(this.index + 1); + } +}); diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-page-selector/viewer-page-selector.css b/atom/browser/resources/pdf_viewer/elements/viewer-page-selector/viewer-page-selector.css new file mode 100644 index 00000000000..ab124ab262f --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-page-selector/viewer-page-selector.css @@ -0,0 +1,52 @@ +/* Copyright 2015 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. */ + +:host { + color: #fff; + font-size: 94.4%; +} + +:host ::selection { + background: rgba(255, 255, 255, 0.3); +} + +#pageselector { + --paper-input-container-underline: { + visibility: hidden; + }; + --paper-input-container-underline-focus: { + visibility: hidden; + }; + display: inline-block; + padding: 0; + width: 1ch; +} + +#input { + -webkit-margin-start: -3px; + color: #fff; + line-height: 18px; + padding: 3px; + text-align: end; +} + +#input:focus, +#input:hover { + background-color: rgba(0, 0, 0, 0.5); + border-radius: 2px; +} + +#slash { + padding: 0 3px; +} + +#pagelength-spacer { + display: inline-block; + text-align: start; +} + +#slash, +#pagelength { + font-size: 76.5%; +} diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-page-selector/viewer-page-selector.html b/atom/browser/resources/pdf_viewer/elements/viewer-page-selector/viewer-page-selector.html new file mode 100644 index 00000000000..bebbd75400c --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-page-selector/viewer-page-selector.html @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-page-selector/viewer-page-selector.js b/atom/browser/resources/pdf_viewer/elements/viewer-page-selector/viewer-page-selector.js new file mode 100644 index 00000000000..ad344f60e13 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-page-selector/viewer-page-selector.js @@ -0,0 +1,59 @@ +// Copyright 2015 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. + +Polymer({ + is: 'viewer-page-selector', + + properties: { + /** + * The number of pages the document contains. + */ + docLength: { + type: Number, + value: 1, + observer: 'docLengthChanged' + }, + + /** + * The current page being viewed (1-based). A change to pageNo is mirrored + * immediately to the input field. A change to the input field is not + * mirrored back until pageNoCommitted() is called and change-page is fired. + */ + pageNo: { + type: Number, + value: 1 + }, + + strings: Object, + }, + + pageNoCommitted: function() { + var page = parseInt(this.$.input.value); + + if (!isNaN(page) && page <= this.docLength && page > 0) + this.fire('change-page', {page: page - 1}); + else + this.$.input.value = this.pageNo; + this.$.input.blur(); + }, + + docLengthChanged: function() { + var numDigits = this.docLength.toString().length; + this.$.pageselector.style.width = numDigits + 'ch'; + // Set both sides of the slash to the same width, so that the layout is + // exactly centered. + this.$['pagelength-spacer'].style.width = numDigits + 'ch'; + }, + + select: function() { + this.$.input.select(); + }, + + /** + * @return {boolean} True if the selector input field is currently focused. + */ + isActive: function() { + return this.shadowRoot.activeElement == this.$.input; + } +}); diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-password-screen/viewer-password-screen.html b/atom/browser/resources/pdf_viewer/elements/viewer-password-screen/viewer-password-screen.html new file mode 100644 index 00000000000..343f579f437 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-password-screen/viewer-password-screen.html @@ -0,0 +1,30 @@ + + + + + + + + + + + + diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-password-screen/viewer-password-screen.js b/atom/browser/resources/pdf_viewer/elements/viewer-password-screen/viewer-password-screen.js new file mode 100644 index 00000000000..2ba723e995a --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-password-screen/viewer-password-screen.js @@ -0,0 +1,57 @@ +// Copyright 2014 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. + +Polymer({ + is: 'viewer-password-screen', + + properties: { + invalid: Boolean, + + active: { + type: Boolean, + value: false, + observer: 'activeChanged' + }, + + strings: Object, + }, + + ready: function() { + this.activeChanged(); + }, + + accept: function() { + this.active = false; + }, + + deny: function() { + this.$.password.disabled = false; + this.$.submit.disabled = false; + this.invalid = true; + this.$.password.focus(); + this.$.password.select(); + }, + + handleKey: function(e) { + if (e.keyCode == 13) + this.submit(); + }, + + submit: function() { + if (this.$.password.value.length == 0) + return; + this.$.password.disabled = true; + this.$.submit.disabled = true; + this.fire('password-submitted', {password: this.$.password.value}); + }, + + activeChanged: function() { + if (this.active) { + this.$.dialog.open(); + this.$.password.focus(); + } else { + this.$.dialog.close(); + } + } +}); diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.css b/atom/browser/resources/pdf_viewer/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.css new file mode 100644 index 00000000000..37e8401816e --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.css @@ -0,0 +1,92 @@ +/* Copyright 2015 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. */ + +:host ::selection { + background: rgba(255, 255, 255, 0.3); +} + +/* We introduce a wrapper aligner element to help with laying out the main + * toolbar content without changing the bottom-aligned progress bar. */ +#aligner { + @apply(--layout-horizontal); + @apply(--layout-center); + padding: 0 16px; + width: 100%; +} + +#title { + @apply(--layout-flex-5); + font-size: 77.8%; + font-weight: 500; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +#pageselector-container { + @apply(--layout-flex-1); + text-align: center; + /* The container resizes according to the width of the toolbar. On small + * screens with large numbers of pages, overflow page numbers without + * wrapping. */ + white-space: nowrap; +} + +#buttons { + @apply(--layout-flex-5); + -webkit-user-select: none; + text-align: end; +} + +paper-icon-button { + -webkit-margin-end: 12px; +} + +viewer-toolbar-dropdown { + -webkit-margin-end: 4px; +} + +paper-progress { + --paper-progress-active-color: var(--google-blue-300); + --paper-progress-container-color: transparent; + --paper-progress-height: 3px; + transition: opacity 150ms; + width: 100%; +} + +paper-toolbar { + --paper-toolbar-background: rgb(50, 54, 57); + --paper-toolbar-height: 48px; + @apply(--shadow-elevation-2dp); + color: rgb(241, 241, 241); + font-size: 1.5em; +} + +.invisible { + visibility: hidden; +} + +@media(max-width: 675px) { + #bookmarks, + #rotate-left { + display: none; + } + + #pageselector-container { + flex: 2; + } +} + +@media(max-width: 450px) { + #rotate-right { + display: none; + } +} + +@media(max-width: 400px) { + #buttons, + #pageselector-container { + display: none; + } +} diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html b/atom/browser/resources/pdf_viewer/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html new file mode 100644 index 00000000000..ca028bd0507 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.js b/atom/browser/resources/pdf_viewer/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.js new file mode 100644 index 00000000000..d4e8cbd6637 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.js @@ -0,0 +1,146 @@ +// Copyright 2015 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. +(function() { + Polymer({ + is: 'viewer-pdf-toolbar', + + behaviors: [ + Polymer.NeonAnimationRunnerBehavior + ], + + properties: { + /** + * The current loading progress of the PDF document (0 - 100). + */ + loadProgress: { + type: Number, + observer: 'loadProgressChanged' + }, + + /** + * The title of the PDF document. + */ + docTitle: String, + + /** + * The number of the page being viewed (1-based). + */ + pageNo: Number, + + /** + * Tree of PDF bookmarks (or null if the document has no bookmarks). + */ + bookmarks: { + type: Object, + value: null + }, + + /** + * The number of pages in the PDF document. + */ + docLength: Number, + + /** + * Whether the toolbar is opened and visible. + */ + opened: { + type: Boolean, + value: true + }, + + strings: Object, + + animationConfig: { + value: function() { + return { + 'entry': { + name: 'transform-animation', + node: this, + transformFrom: 'translateY(-100%)', + transformTo: 'translateY(0%)', + timing: { + easing: 'cubic-bezier(0, 0, 0.2, 1)', + duration: 250 + } + }, + 'exit': { + name: 'slide-up-animation', + node: this, + timing: { + easing: 'cubic-bezier(0.4, 0, 1, 1)', + duration: 250 + } + } + }; + } + } + }, + + listeners: { + 'neon-animation-finish': '_onAnimationFinished' + }, + + _onAnimationFinished: function() { + this.style.transform = this.opened ? 'none' : 'translateY(-100%)'; + }, + + loadProgressChanged: function() { + if (this.loadProgress >= 100) { + this.$.pageselector.classList.toggle('invisible', false); + this.$.buttons.classList.toggle('invisible', false); + this.$.progress.style.opacity = 0; + } + }, + + hide: function() { + if (this.opened) + this.toggleVisibility(); + }, + + show: function() { + if (!this.opened) { + this.toggleVisibility(); + } + }, + + toggleVisibility: function() { + this.opened = !this.opened; + this.cancelAnimation(); + this.playAnimation(this.opened ? 'entry' : 'exit'); + }, + + selectPageNumber: function() { + this.$.pageselector.select(); + }, + + shouldKeepOpen: function() { + return this.$.bookmarks.dropdownOpen || this.loadProgress < 100 || + this.$.pageselector.isActive(); + }, + + hideDropdowns: function() { + if (this.$.bookmarks.dropdownOpen) { + this.$.bookmarks.toggleDropdown(); + return true; + } + return false; + }, + + setDropdownLowerBound: function(lowerBound) { + this.$.bookmarks.lowerBound = lowerBound; + }, + + rotateRight: function() { + this.fire('rotate-right'); + }, + + download: function() { + this.fire('save'); + }, + + print: function() { + this.fire('print'); + } + }); +})(); diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.css b/atom/browser/resources/pdf_viewer/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.css new file mode 100644 index 00000000000..5a6d55bf20c --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.css @@ -0,0 +1,59 @@ +/* Copyright 2015 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. */ + +:host { + text-align: start; +} + +#container { + position: absolute; + /* Controls the position of the dropdown relative to the right of the screen. + * Default is aligned with the right of the toolbar buttons. + * TODO(tsergeant): Change the layout of the dropdown so this is not required. + */ + right: var(--viewer-toolbar-dropdown-right-distance, 36px); +} + +:host-context([dir=rtl]) #container { + left: var(--viewer-toolbar-dropdown-right-distance, 36px); + right: auto; +} + +paper-material { + background-color: rgb(256, 256, 256); + border-radius: 4px; + overflow-y: hidden; + padding-bottom: 2px; + width: 260px; +} + +#scroll-container { + max-height: 300px; + overflow-y: auto; + padding: 6px 0 4px 0; +} + +#icon { + cursor: pointer; + display: inline-block; +} + +:host([dropdown-open]) #icon { + background-color: rgb(25, 27, 29); + border-radius: 4px; +} + +#arrow { + -webkit-margin-start: -12px; + -webkit-padding-end: 4px; +} + +h1 { + border-bottom: 1px solid rgb(219, 219, 219); + color: rgb(33, 33, 33); + font-size: 77.8%; + font-weight: 500; + margin: 0; + padding: 14px 28px; +} diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html b/atom/browser/resources/pdf_viewer/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html new file mode 100644 index 00000000000..e759825c94b --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html @@ -0,0 +1,29 @@ + + + + + + + + + + + + + diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.js b/atom/browser/resources/pdf_viewer/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.js new file mode 100644 index 00000000000..17a04c04d7b --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.js @@ -0,0 +1,138 @@ +// Copyright 2015 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. + +(function() { + /** + * Size of additional padding in the inner scrollable section of the dropdown. + */ + var DROPDOWN_INNER_PADDING = 12; + + /** Size of vertical padding on the outer #dropdown element. */ + var DROPDOWN_OUTER_PADDING = 2; + + /** Minimum height of toolbar dropdowns (px). */ + var MIN_DROPDOWN_HEIGHT = 200; + + Polymer({ + is: 'viewer-toolbar-dropdown', + + properties: { + /** String to be displayed at the top of the dropdown. */ + header: String, + + /** Icon to display when the dropdown is closed. */ + closedIcon: String, + + /** Icon to display when the dropdown is open. */ + openIcon: String, + + /** True if the dropdown is currently open. */ + dropdownOpen: { + type: Boolean, + reflectToAttribute: true, + value: false + }, + + /** Toolbar icon currently being displayed. */ + dropdownIcon: { + type: String, + computed: 'computeIcon_(dropdownOpen, closedIcon, openIcon)' + }, + + /** Lowest vertical point that the dropdown should occupy (px). */ + lowerBound: { + type: Number, + observer: 'lowerBoundChanged_' + }, + + /** + * True if the max-height CSS property for the dropdown scroll container + * is valid. If false, the height will be updated the next time the + * dropdown is visible. + */ + maxHeightValid_: false, + + /** Current animation being played, or null if there is none. */ + animation_: Object + }, + + computeIcon_: function(dropdownOpen, closedIcon, openIcon) { + return dropdownOpen ? openIcon : closedIcon; + }, + + lowerBoundChanged_: function() { + this.maxHeightValid_ = false; + if (this.dropdownOpen) + this.updateMaxHeight(); + }, + + toggleDropdown: function() { + this.dropdownOpen = !this.dropdownOpen; + if (this.dropdownOpen) { + this.$.dropdown.style.display = 'block'; + if (!this.maxHeightValid_) + this.updateMaxHeight(); + } + this.cancelAnimation_(); + this.playAnimation_(this.dropdownOpen); + }, + + updateMaxHeight: function() { + var scrollContainer = this.$['scroll-container']; + var height = this.lowerBound - + scrollContainer.getBoundingClientRect().top - + DROPDOWN_INNER_PADDING; + height = Math.max(height, MIN_DROPDOWN_HEIGHT); + scrollContainer.style.maxHeight = height + 'px'; + this.maxHeightValid_ = true; + }, + + cancelAnimation_: function() { + if (this._animation) + this._animation.cancel(); + }, + + /** + * Start an animation on the dropdown. + * @param {boolean} isEntry True to play entry animation, false to play + * exit. + * @private + */ + playAnimation_: function(isEntry) { + this.animation_ = isEntry ? this.animateEntry_() : this.animateExit_(); + this.animation_.onfinish = function() { + this.animation_ = null; + if (!this.dropdownOpen) + this.$.dropdown.style.display = 'none'; + }.bind(this); + }, + + animateEntry_: function() { + var maxHeight = this.$.dropdown.getBoundingClientRect().height - + DROPDOWN_OUTER_PADDING; + + if (maxHeight < 0) + maxHeight = 0; + + var fade = new KeyframeEffect(this.$.dropdown, [ + {opacity: 0}, + {opacity: 1} + ], {duration: 150, easing: 'cubic-bezier(0, 0, 0.2, 1)'}); + var slide = new KeyframeEffect(this.$.dropdown, [ + {height: '20px', transform: 'translateY(-10px)'}, + {height: maxHeight + 'px', transform: 'translateY(0)'} + ], {duration: 250, easing: 'cubic-bezier(0, 0, 0.2, 1)'}); + + return document.timeline.play(new GroupEffect([fade, slide])); + }, + + animateExit_: function() { + return this.$.dropdown.animate([ + {transform: 'translateY(0)', opacity: 1}, + {transform: 'translateY(-5px)', opacity: 0} + ], {duration: 100, easing: 'cubic-bezier(0.4, 0, 1, 1)'}); + } + }); + +})(); diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-button.css b/atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-button.css new file mode 100644 index 00000000000..02454185593 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-button.css @@ -0,0 +1,32 @@ +/* Copyright 2015 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. */ + +#wrapper { + transition: transform 250ms; + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); +} + +:host([closed]) #wrapper { + /* 132px roughly flips the location of the button across the right edge of the + * page. */ + transform: translateX(132px); + transition-timing-function: cubic-bezier(0.4, 0, 1, 1); +} + +:host-context([dir=rtl]):host([closed]) #wrapper { + transform: translateX(-132px); +} + +paper-fab { + --paper-fab-keyboard-focus-background: var(--viewer-icon-ink-color); + --paper-fab-mini: { + height: 36px; + padding: 8px; + width: 36px; + }; + @apply(--shadow-elevation-4dp); + background-color: rgb(242, 242, 242); + color: rgb(96, 96, 96); + overflow: visible; +} diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-button.html b/atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-button.html new file mode 100644 index 00000000000..8108d7d7a1a --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-button.html @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-button.js b/atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-button.js new file mode 100644 index 00000000000..df556aced28 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-button.js @@ -0,0 +1,95 @@ +// Copyright 2015 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. + +Polymer({ + is: 'viewer-zoom-button', + + properties: { + /** + * Icons to be displayed on the FAB. Multiple icons should be separated with + * spaces, and will be cycled through every time the FAB is clicked. + */ + icons: String, + + /** + * Array version of the list of icons. Polymer does not allow array + * properties to be set from HTML, so we must use a string property and + * perform the conversion manually. + * @private + */ + icons_: { + type: Array, + value: [''], + computed: 'computeIconsArray_(icons)' + }, + + tooltips: Array, + + closed: { + type: Boolean, + reflectToAttribute: true, + value: false + }, + + delay: { + type: Number, + observer: 'delayChanged_' + }, + + /** + * Index of the icon currently being displayed. + */ + activeIndex: { + type: Number, + value: 0 + }, + + /** + * Icon currently being displayed on the FAB. + * @private + */ + visibleIcon_: { + type: String, + computed: 'computeVisibleIcon_(icons_, activeIndex)' + }, + + visibleTooltip_: { + type: String, + computed: 'computeVisibleTooltip_(tooltips, activeIndex)' + } + }, + + computeIconsArray_: function(icons) { + return icons.split(' '); + }, + + computeVisibleIcon_: function(icons, activeIndex) { + return icons[activeIndex]; + }, + + computeVisibleTooltip_: function(tooltips, activeIndex) { + return tooltips[activeIndex]; + }, + + delayChanged_: function() { + this.$.wrapper.style.transitionDelay = this.delay + 'ms'; + }, + + show: function() { + this.closed = false; + }, + + hide: function() { + this.closed = true; + }, + + fireClick: function() { + // We cannot attach an on-click to the entire viewer-zoom-button, as this + // will include clicks on the margins. Instead, proxy clicks on the FAB + // through. + this.fire('fabclick'); + + this.activeIndex = (this.activeIndex + 1) % this.icons_.length; + } +}); diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.css b/atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.css new file mode 100644 index 00000000000..c7577ef5471 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.css @@ -0,0 +1,41 @@ +/* Copyright 2015 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. */ + +:host { + -webkit-user-select: none; + bottom: 0; + padding: 48px 0; + position: fixed; + right: 0; + z-index: 3; +} + +:host-context([dir=rtl]) { + left: 0; + right: auto; +} + +#zoom-buttons { + position: relative; + right: 48px; +} + +:host-context([dir=rtl]) #zoom-buttons { + left: 48px; + right: auto; +} + +viewer-zoom-button { + display: block; +} + +/* A small gap between the zoom in/zoom out buttons. */ +#zoom-out-button { + margin-top: 10px; +} + +/* A larger gap between the fit button and bottom two buttons. */ +#zoom-in-button { + margin-top: 24px; +} diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.html b/atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.html new file mode 100644 index 00000000000..ff8c21ee719 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.html @@ -0,0 +1,21 @@ + + + + + + + + + + diff --git a/atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.js b/atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.js new file mode 100644 index 00000000000..060178fcc6f --- /dev/null +++ b/atom/browser/resources/pdf_viewer/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.js @@ -0,0 +1,75 @@ +// Copyright 2015 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. + +(function() { + + var FIT_TO_PAGE = 0; + var FIT_TO_WIDTH = 1; + + Polymer({ + is: 'viewer-zoom-toolbar', + + properties: { + strings: { + type: Object, + observer: 'updateTooltips_' + }, + + visible_: { + type: Boolean, + value: true + } + }, + + isVisible: function() { + return this.visible_; + }, + + /** + * Change button tooltips to match any changes to localized strings. + */ + updateTooltips_: function() { + this.$['fit-button'].tooltips = [ + this.strings.tooltipFitToPage, + this.strings.tooltipFitToWidth + ]; + this.$['zoom-in-button'].tooltips = [this.strings.tooltipZoomIn]; + this.$['zoom-out-button'].tooltips = [this.strings.tooltipZoomOut]; + }, + + fitToggle: function() { + if (this.$['fit-button'].activeIndex == FIT_TO_WIDTH) + this.fire('fit-to-width'); + else + this.fire('fit-to-page'); + }, + + zoomIn: function() { + this.fire('zoom-in'); + }, + + zoomOut: function() { + this.fire('zoom-out'); + }, + + show: function() { + if (!this.visible_) { + this.visible_ = true; + this.$['fit-button'].show(); + this.$['zoom-in-button'].show(); + this.$['zoom-out-button'].show(); + } + }, + + hide: function() { + if (this.visible_) { + this.visible_ = false; + this.$['fit-button'].hide(); + this.$['zoom-in-button'].hide(); + this.$['zoom-out-button'].hide(); + } + }, + }); + +})(); diff --git a/atom/browser/resources/pdf_viewer/index.css b/atom/browser/resources/pdf_viewer/index.css new file mode 100644 index 00000000000..a443bac50ec --- /dev/null +++ b/atom/browser/resources/pdf_viewer/index.css @@ -0,0 +1,50 @@ +/* Copyright 2015 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. */ + +body { + background-color: rgb(82, 86, 89); + font-family: 'Roboto', 'Noto', sans-serif; + margin: 0; +} + +viewer-page-indicator { + visibility: hidden; + z-index: 2; +} + +viewer-pdf-toolbar { + position: fixed; + width: 100%; + z-index: 4; +} + +#plugin { + height: 100%; + position: fixed; + width: 100%; + z-index: 1; +} + +#sizer { + position: absolute; + z-index: 0; +} + +@media(max-height: 250px) { + viewer-pdf-toolbar { + display: none; + } +} + +@media(max-height: 200px) { + viewer-zoom-toolbar { + display: none; + } +} + +@media(max-width: 300px) { + viewer-zoom-toolbar { + display: none; + } +} diff --git a/atom/browser/resources/pdf_viewer/index.html b/atom/browser/resources/pdf_viewer/index.html new file mode 100644 index 00000000000..e479ff7d985 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/index.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + diff --git a/atom/browser/resources/pdf_viewer/main.js b/atom/browser/resources/pdf_viewer/main.js new file mode 100644 index 00000000000..9496a175683 --- /dev/null +++ b/atom/browser/resources/pdf_viewer/main.js @@ -0,0 +1,55 @@ +// Copyright 2014 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. + +'use strict'; + +/** + * Global PDFViewer object, accessible for testing. + * @type Object + */ +var viewer; + + +//(function() { + /** + * Stores any pending messages received which should be passed to the + * PDFViewer when it is created. + * @type Array + */ + var pendingMessages = []; + + /** + * Handles events that are received prior to the PDFViewer being created. + * @param {Object} message A message event received. + */ + function handleScriptingMessage(message) { + pendingMessages.push(message); + } + + /** + * Initialize the global PDFViewer and pass any outstanding messages to it. + * @param {Object} browserApi An object providing an API to the browser. + */ + function initViewer(browserApi) { + // PDFViewer will handle any messages after it is created. + window.removeEventListener('message', handleScriptingMessage, false); + viewer = new PDFViewer(browserApi); + while (pendingMessages.length > 0) + viewer.handleScriptingMessage(pendingMessages.shift()); + } + + /** + * Entrypoint for starting the PDF viewer. This function obtains the browser + * API for the PDF and constructs a PDFViewer object with it. + */ + function main(streamURL, originalURL) { + // Set up an event listener to catch scripting messages which are sent prior + // to the PDFViewer being created. + window.addEventListener('message', handleScriptingMessage, false); + + createBrowserApi(streamURL, originalURL).then(initViewer); + }; + + //main(); +//})(); diff --git a/atom/browser/resources/pdf_viewer/navigator.js b/atom/browser/resources/pdf_viewer/navigator.js new file mode 100644 index 00000000000..611b4a91bde --- /dev/null +++ b/atom/browser/resources/pdf_viewer/navigator.js @@ -0,0 +1,211 @@ +// Copyright 2015 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. + +'use strict'; + +/** + * Creates a new Navigator for navigating to links inside or outside the PDF. + * @param {string} originalUrl The original page URL. + * @param {Object} viewport The viewport info of the page. + * @param {Object} paramsParser The object for URL parsing. + * @param {Function} navigateInCurrentTabCallback The Callback function that + * gets called when navigation happens in the current tab. + * @param {Function} navigateInNewTabCallback The Callback function + * that gets called when navigation happens in the new tab. + */ +function Navigator(originalUrl, + viewport, + paramsParser, + navigateInCurrentTabCallback, + navigateInNewTabCallback) { + this.originalUrl_ = originalUrl; + this.viewport_ = viewport; + this.paramsParser_ = paramsParser; + this.navigateInCurrentTabCallback_ = navigateInCurrentTabCallback; + this.navigateInNewTabCallback_ = navigateInNewTabCallback; +} + +/** + * Represents options when navigating to a new url. C++ counterpart of + * the enum is in ui/base/window_open_disposition.h. This enum represents + * the only values that are passed from Plugin. + * @enum {number} + */ +Navigator.WindowOpenDisposition = { + CURRENT_TAB: 1, + NEW_FOREGROUND_TAB: 3, + NEW_BACKGROUND_TAB: 4, + NEW_WINDOW: 6, + SAVE_TO_DISK: 7 +}; + +Navigator.prototype = { + /** + * @private + * Function to navigate to the given URL. This might involve navigating + * within the PDF page or opening a new url (in the same tab or a new tab). + * @param {string} url The URL to navigate to. + * @param {number} disposition The window open disposition when + * navigating to the new URL. + */ + navigate: function(url, disposition) { + if (url.length == 0) + return; + + // If |urlFragment| starts with '#', then it's for the same URL with a + // different URL fragment. + if (url.charAt(0) == '#') { + // if '#' is already present in |originalUrl| then remove old fragment + // and add new url fragment. + var hashIndex = this.originalUrl_.search('#'); + if (hashIndex != -1) + url = this.originalUrl_.substring(0, hashIndex) + url; + else + url = this.originalUrl_ + url; + } + + // If there's no scheme, then take a guess at the scheme. + if (url.indexOf('://') == -1 && url.indexOf('mailto:') == -1) + url = this.guessUrlWithoutScheme_(url); + + if (!this.isValidUrl_(url)) + return; + + switch (disposition) { + case Navigator.WindowOpenDisposition.CURRENT_TAB: + this.paramsParser_.getViewportFromUrlParams( + url, this.onViewportReceived_.bind(this)); + break; + case Navigator.WindowOpenDisposition.NEW_BACKGROUND_TAB: + this.navigateInNewTabCallback_(url, false); + break; + case Navigator.WindowOpenDisposition.NEW_FOREGROUND_TAB: + this.navigateInNewTabCallback_(url, true); + break; + case Navigator.WindowOpenDisposition.NEW_WINDOW: + // TODO(jaepark): Shift + left clicking a link in PDF should open the + // link in a new window. See http://crbug.com/628057. + this.paramsParser_.getViewportFromUrlParams( + url, this.onViewportReceived_.bind(this)); + break; + case Navigator.WindowOpenDisposition.SAVE_TO_DISK: + // TODO(jaepark): Alt + left clicking a link in PDF should + // download the link. + this.paramsParser_.getViewportFromUrlParams( + url, this.onViewportReceived_.bind(this)); + break; + default: + break; + } + }, + + /** + * @private + * Called when the viewport position is received. + * @param {Object} viewportPosition Dictionary containing the viewport + * position. + */ + onViewportReceived_: function(viewportPosition) { + var originalUrl = this.originalUrl_; + var hashIndex = originalUrl.search('#'); + if (hashIndex != -1) + originalUrl = originalUrl.substring(0, hashIndex); + + var newUrl = viewportPosition.url; + hashIndex = newUrl.search('#'); + if (hashIndex != -1) + newUrl = newUrl.substring(0, hashIndex); + + var pageNumber = viewportPosition.page; + if (pageNumber != undefined && originalUrl == newUrl) + this.viewport_.goToPage(pageNumber); + else + this.navigateInCurrentTabCallback_(viewportPosition.url); + }, + + /** + * @private + * Checks if the URL starts with a scheme and s not just a scheme. + * @param {string} The input URL + * @return {boolean} Whether the url is valid. + */ + isValidUrl_: function(url) { + // Make sure |url| starts with a valid scheme. + if (url.indexOf('http://') != 0 && + url.indexOf('https://') != 0 && + url.indexOf('ftp://') != 0 && + url.indexOf('file://') != 0 && + url.indexOf('mailto:') != 0) { + return false; + } + + // Make sure |url| is not only a scheme. + if (url == 'http://' || + url == 'https://' || + url == 'ftp://' || + url == 'file://' || + url == 'mailto:') { + return false; + } + + return true; + }, + + /** + * @private + * Attempt to figure out what a URL is when there is no scheme. + * @param {string} The input URL + * @return {string} The URL with a scheme or the original URL if it is not + * possible to determine the scheme. + */ + guessUrlWithoutScheme_: function(url) { + // If the original URL is mailto:, that does not make sense to start with, + // and neither does adding |url| to it. + // If the original URL is not a valid URL, this cannot make a valid URL. + // In both cases, just bail out. + if (this.originalUrl_.startsWith('mailto:') || + !this.isValidUrl_(this.originalUrl_)) { + return url; + } + + // Check for absolute paths. + if (url.startsWith('/')) { + var schemeEndIndex = this.originalUrl_.indexOf('://'); + var firstSlash = this.originalUrl_.indexOf('/', schemeEndIndex + 3); + // e.g. http://www.foo.com/bar -> http://www.foo.com + var domain = firstSlash != -1 ? + this.originalUrl_.substr(0, firstSlash) : this.originalUrl_; + return domain + url; + } + + // Check for obvious relative paths. + var isRelative = false; + if (url.startsWith('.') || url.startsWith('\\')) + isRelative = true; + + // In Adobe Acrobat Reader XI, it looks as though links with less than + // 2 dot separators in the domain are considered relative links, and + // those with 2 of more are considered http URLs. e.g. + // + // www.foo.com/bar -> http + // foo.com/bar -> relative link + if (!isRelative) { + var domainSeparatorIndex = url.indexOf('/'); + var domainName = domainSeparatorIndex == -1 ? + url : url.substr(0, domainSeparatorIndex); + var domainDotCount = (domainName.match(/\./g) || []).length; + if (domainDotCount < 2) + isRelative = true; + } + + if (isRelative) { + var slashIndex = this.originalUrl_.lastIndexOf('/'); + var path = slashIndex != -1 ? + this.originalUrl_.substr(0, slashIndex) : this.originalUrl_; + return path + '/' + url; + } + + return 'http://' + url; + } +}; diff --git a/atom/browser/resources/pdf_viewer/ods-cpp.pdf b/atom/browser/resources/pdf_viewer/ods-cpp.pdf new file mode 100644 index 0000000000000000000000000000000000000000..592eb38c2c3f3aecb8486d5aceeef153630bbfdf GIT binary patch literal 1519810 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