From: deepak1556 Date: Tue, 17 Jan 2017 14:23:13 +0000 (+0530) Subject: browser: implement pdf renderer as webui X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fdd574cea544ea5608ab9ba56873bcd9bd2c7366;p=platform%2Fframework%2Fweb%2Fcrosswalk-tizen.git browser: implement pdf renderer as webui --- diff --git a/.gitmodules b/.gitmodules index 5bc253b..80cafd9 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 760a427..f1b7a9c 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 4031fb2..eb09b18 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 7858911..1438c22 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 681fec6..2a5ca1e 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 0000000..3682309 --- /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 0000000..d63aa0e --- /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 637792c..1db52bd 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 47bc67b..9a47100 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', ], @@ -418,6 +420,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', 'copies': [ @@ -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 44a6fbf..3c7e4d2 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 24e19b9..7bd707c 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 5a63b20..35a109c 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',