From d309fd5a27d58512fa3890f0437be7b5a53fe5e4 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 7 Dec 2014 06:55:40 -0800 Subject: [PATCH 01/41] Update printing code --- atom.gyp | 3 +- atom/browser/atom_browser_client.cc | 2 +- atom/renderer/atom_renderer_client.cc | 2 +- atom/renderer/atom_renderer_client.h | 2 +- .../chrome/browser/printing/print_job.cc | 69 ++-- .../chrome/browser/printing/print_job.h | 21 +- .../browser/printing/print_job_manager.cc | 33 +- .../browser/printing/print_job_manager.h | 10 +- .../browser/printing/print_job_worker.cc | 210 +++++++----- .../browser/printing/print_job_worker.h | 60 ++-- .../printing/print_job_worker_owner.cc | 27 ++ .../browser/printing/print_job_worker_owner.h | 24 +- .../printing/print_view_manager_base.cc | 82 ++--- .../printing/print_view_manager_base.h | 9 +- .../chrome/browser/printing/printer_query.cc | 47 +-- .../chrome/browser/printing/printer_query.h | 16 +- .../printing/printing_message_filter.cc | 306 +++++++++++++----- .../printing/printing_message_filter.h | 63 ++-- .../printing/print_web_view_helper.cc | 78 ++--- .../renderer/printing/print_web_view_helper.h | 55 ++-- .../printing/print_web_view_helper_linux.cc | 13 +- .../printing/print_web_view_helper_mac.mm | 16 +- vendor/brightray | 2 +- 23 files changed, 665 insertions(+), 485 deletions(-) create mode 100644 chromium_src/chrome/browser/printing/print_job_worker_owner.cc diff --git a/atom.gyp b/atom.gyp index e3c9eeab71..3c368b1b9e 100644 --- a/atom.gyp +++ b/atom.gyp @@ -283,6 +283,7 @@ 'chromium_src/chrome/browser/printing/print_job_manager.h', 'chromium_src/chrome/browser/printing/print_job_worker.cc', 'chromium_src/chrome/browser/printing/print_job_worker.h', + 'chromium_src/chrome/browser/printing/print_job_worker_owner.cc', 'chromium_src/chrome/browser/printing/print_job_worker_owner.h', 'chromium_src/chrome/browser/printing/print_view_manager_base.cc', 'chromium_src/chrome/browser/printing/print_view_manager_base.h', @@ -293,8 +294,6 @@ 'chromium_src/chrome/browser/printing/printer_query.h', 'chromium_src/chrome/browser/printing/printing_message_filter.cc', 'chromium_src/chrome/browser/printing/printing_message_filter.h', - 'chromium_src/chrome/browser/printing/printing_ui_web_contents_observer.cc', - 'chromium_src/chrome/browser/printing/printing_ui_web_contents_observer.h', 'chromium_src/chrome/browser/speech/tts_controller.h', 'chromium_src/chrome/browser/speech/tts_controller_impl.cc', 'chromium_src/chrome/browser/speech/tts_controller_impl.h', diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index c39acc06ca..7b908676b1 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -56,7 +56,7 @@ AtomBrowserClient::~AtomBrowserClient() { void AtomBrowserClient::RenderProcessWillLaunch( content::RenderProcessHost* host) { int id = host->GetID(); - host->AddFilter(new PrintingMessageFilter(host->GetID())); + host->AddFilter(new printing::PrintingMessageFilter(host->GetID())); host->AddFilter(new TtsMessageFilter(id, host->GetBrowserContext())); } diff --git a/atom/renderer/atom_renderer_client.cc b/atom/renderer/atom_renderer_client.cc index 91d83bf1f4..7a108d72c5 100644 --- a/atom/renderer/atom_renderer_client.cc +++ b/atom/renderer/atom_renderer_client.cc @@ -161,7 +161,7 @@ void AtomRendererClient::DidCreateScriptContext(blink::WebFrame* frame, } void AtomRendererClient::WillReleaseScriptContext( - blink::WebFrame* frame, + blink::WebLocalFrame* frame, v8::Handle context, int world_id) { node::Environment* env = node::Environment::GetCurrent(context); diff --git a/atom/renderer/atom_renderer_client.h b/atom/renderer/atom_renderer_client.h index cb461b2bca..ed2c1e1ad7 100644 --- a/atom/renderer/atom_renderer_client.h +++ b/atom/renderer/atom_renderer_client.h @@ -27,7 +27,7 @@ class AtomRendererClient : public content::ContentRendererClient, virtual ~AtomRendererClient(); // Forwarded by RenderFrameObserver. - void WillReleaseScriptContext(blink::WebFrame* frame, + void WillReleaseScriptContext(blink::WebLocalFrame* frame, v8::Handle context, int world_id); diff --git a/chromium_src/chrome/browser/printing/print_job.cc b/chromium_src/chrome/browser/printing/print_job.cc index 4a58440685..25cf0ad790 100644 --- a/chromium_src/chrome/browser/printing/print_job.cc +++ b/chromium_src/chrome/browser/printing/print_job.cc @@ -32,29 +32,25 @@ void HoldRefCallback(const scoped_refptr& owner, namespace printing { PrintJob::PrintJob() - : ui_message_loop_(base::MessageLoop::current()), - source_(NULL), + : source_(NULL), worker_(), settings_(), is_job_pending_(false), is_canceling_(false), quit_factory_(this) { - DCHECK(ui_message_loop_); // This is normally a UI message loop, but in unit tests, the message loop is // of the 'default' type. DCHECK(base::MessageLoopForUI::IsCurrent() || - ui_message_loop_->type() == base::MessageLoop::TYPE_DEFAULT); - ui_message_loop_->AddDestructionObserver(this); + base::MessageLoop::current()->type() == + base::MessageLoop::TYPE_DEFAULT); } PrintJob::~PrintJob() { - ui_message_loop_->RemoveDestructionObserver(this); // The job should be finished (or at least canceled) when it is destroyed. DCHECK(!is_job_pending_); DCHECK(!is_canceling_); - if (worker_.get()) - DCHECK(worker_->message_loop() == NULL); - DCHECK_EQ(ui_message_loop_, base::MessageLoop::current()); + DCHECK(!worker_ || !worker_->IsRunning()); + DCHECK(RunsTasksOnCurrentThread()); } void PrintJob::Initialize(PrintJobWorkerOwner* job, @@ -85,7 +81,7 @@ void PrintJob::Initialize(PrintJobWorkerOwner* job, void PrintJob::Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) { - DCHECK_EQ(ui_message_loop_, base::MessageLoop::current()); + DCHECK(RunsTasksOnCurrentThread()); switch (type) { case chrome::NOTIFICATION_PRINT_JOB_EVENT: { OnNotifyPrintJobEvent(*content::Details(details).ptr()); @@ -107,10 +103,6 @@ PrintJobWorker* PrintJob::DetachWorker(PrintJobWorkerOwner* new_owner) { return NULL; } -base::MessageLoop* PrintJob::message_loop() { - return ui_message_loop_; -} - const PrintSettings& PrintJob::settings() const { return settings_; } @@ -122,23 +114,20 @@ int PrintJob::cookie() const { return document_->cookie(); } -void PrintJob::WillDestroyCurrentMessageLoop() { - NOTREACHED(); -} - void PrintJob::StartPrinting() { - DCHECK_EQ(ui_message_loop_, base::MessageLoop::current()); - DCHECK(worker_->message_loop()); + DCHECK(RunsTasksOnCurrentThread()); + DCHECK(worker_->IsRunning()); DCHECK(!is_job_pending_); - if (!worker_->message_loop() || is_job_pending_) + if (!worker_->IsRunning() || is_job_pending_) return; // Real work is done in PrintJobWorker::StartPrinting(). - worker_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&HoldRefCallback, make_scoped_refptr(this), - base::Bind(&PrintJobWorker::StartPrinting, - base::Unretained(worker_.get()), document_))); + worker_->PostTask(FROM_HERE, + base::Bind(&HoldRefCallback, + make_scoped_refptr(this), + base::Bind(&PrintJobWorker::StartPrinting, + base::Unretained(worker_.get()), + document_))); // Set the flag right now. is_job_pending_ = true; @@ -152,7 +141,7 @@ void PrintJob::StartPrinting() { } void PrintJob::Stop() { - DCHECK_EQ(ui_message_loop_, base::MessageLoop::current()); + DCHECK(RunsTasksOnCurrentThread()); if (quit_factory_.HasWeakPtrs()) { // In case we're running a nested message loop to wait for a job to finish, @@ -164,7 +153,7 @@ void PrintJob::Stop() { // Be sure to live long enough. scoped_refptr handle(this); - if (worker_->message_loop()) { + if (worker_->IsRunning()) { ControlledWorkerShutdown(); } else { // Flush the cached document. @@ -180,10 +169,8 @@ void PrintJob::Cancel() { // Be sure to live long enough. scoped_refptr handle(this); - DCHECK_EQ(ui_message_loop_, base::MessageLoop::current()); - base::MessageLoop* worker_loop = - worker_.get() ? worker_->message_loop() : NULL; - if (worker_loop) { + DCHECK(RunsTasksOnCurrentThread()); + if (worker_ && worker_->IsRunning()) { // Call this right now so it renders the context invalid. Do not use // InvokeLater since it would take too much time. worker_->Cancel(); @@ -237,14 +224,15 @@ void PrintJob::UpdatePrintedDocument(PrintedDocument* new_document) { settings_ = document_->settings(); } - if (worker_.get() && worker_->message_loop()) { + if (worker_) { DCHECK(!is_job_pending_); // Sync the document with the worker. - worker_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&HoldRefCallback, make_scoped_refptr(this), - base::Bind(&PrintJobWorker::OnDocumentChanged, - base::Unretained(worker_.get()), document_))); + worker_->PostTask(FROM_HERE, + base::Bind(&HoldRefCallback, + make_scoped_refptr(this), + base::Bind(&PrintJobWorker::OnDocumentChanged, + base::Unretained(worker_.get()), + document_))); } } @@ -264,7 +252,6 @@ void PrintJob::OnNotifyPrintJobEvent(const JobEventDetails& event_details) { } case JobEventDetails::NEW_DOC: case JobEventDetails::NEW_PAGE: - case JobEventDetails::PAGE_DONE: case JobEventDetails::JOB_DONE: case JobEventDetails::ALL_PAGES_REQUESTED: { // Don't care. @@ -276,6 +263,8 @@ void PrintJob::OnNotifyPrintJobEvent(const JobEventDetails& event_details) { FROM_HERE, base::Bind(&PrintJob::OnDocumentDone, this)); break; } + case JobEventDetails::PAGE_DONE: + break; default: { NOTREACHED(); break; @@ -300,7 +289,7 @@ void PrintJob::OnDocumentDone() { } void PrintJob::ControlledWorkerShutdown() { - DCHECK_EQ(ui_message_loop_, base::MessageLoop::current()); + DCHECK(RunsTasksOnCurrentThread()); // The deadlock this code works around is specific to window messaging on // Windows, so we aren't likely to need it on any other platforms. diff --git a/chromium_src/chrome/browser/printing/print_job.h b/chromium_src/chrome/browser/printing/print_job.h index 2ff827a8ed..1b816085c6 100644 --- a/chromium_src/chrome/browser/printing/print_job.h +++ b/chromium_src/chrome/browser/printing/print_job.h @@ -15,15 +15,19 @@ class Thread; +namespace base { +class RefCountedMemory; +} + namespace printing { -// See definition below. class JobEventDetails; - +class MetafilePlayer; +class PdfToEmfConverter; +class PrintJobWorker; class PrintedDocument; class PrintedPage; class PrintedPagesSource; -class PrintJobWorker; class PrinterQuery; // Manages the print work for a specific document. Talks to the printer through @@ -33,8 +37,7 @@ class PrinterQuery; // reference to the job to be sure it is kept alive. All the code in this class // runs in the UI thread. class PrintJob : public PrintJobWorkerOwner, - public content::NotificationObserver, - public base::MessageLoop::DestructionObserver { + public content::NotificationObserver { public: // Create a empty PrintJob. When initializing with this constructor, // post-constructor initialization must be done with Initialize(). @@ -54,13 +57,9 @@ class PrintJob : public PrintJobWorkerOwner, virtual void GetSettingsDone(const PrintSettings& new_settings, PrintingContext::Result result) OVERRIDE; virtual PrintJobWorker* DetachWorker(PrintJobWorkerOwner* new_owner) OVERRIDE; - virtual base::MessageLoop* message_loop() OVERRIDE; virtual const PrintSettings& settings() const OVERRIDE; virtual int cookie() const OVERRIDE; - // DestructionObserver implementation. - virtual void WillDestroyCurrentMessageLoop() OVERRIDE; - // Starts the actual printing. Signals the worker that it should begin to // spool as soon as data is available. void StartPrinting(); @@ -116,10 +115,6 @@ class PrintJob : public PrintJobWorkerOwner, content::NotificationRegistrar registrar_; - // Main message loop reference. Used to send notifications in the right - // thread. - base::MessageLoop* const ui_message_loop_; - // Source that generates the PrintedPage's (i.e. a WebContents). It will be // set back to NULL if the source is deleted before this object. PrintedPagesSource* source_; diff --git a/chromium_src/chrome/browser/printing/print_job_manager.cc b/chromium_src/chrome/browser/printing/print_job_manager.cc index 9dc0c85404..ec08a98923 100644 --- a/chromium_src/chrome/browser/printing/print_job_manager.cc +++ b/chromium_src/chrome/browser/printing/print_job_manager.cc @@ -22,11 +22,6 @@ PrintQueriesQueue::~PrintQueriesQueue() { queued_queries_.clear(); } -void PrintQueriesQueue::SetDestination(PrintDestinationInterface* destination) { - base::AutoLock lock(lock_); - destination_ = destination; -} - void PrintQueriesQueue::QueuePrinterQuery(PrinterQuery* job) { base::AutoLock lock(lock_); DCHECK(job); @@ -49,17 +44,27 @@ scoped_refptr PrintQueriesQueue::PopPrinterQuery( return NULL; } -scoped_refptr PrintQueriesQueue::CreatePrinterQuery() { - scoped_refptr job = new printing::PrinterQuery; - base::AutoLock lock(lock_); - job->SetWorkerDestination(destination_); +scoped_refptr PrintQueriesQueue::CreatePrinterQuery( + int render_process_id, + int render_view_id) { + scoped_refptr job = + new printing::PrinterQuery(render_process_id, render_view_id); return job; } void PrintQueriesQueue::Shutdown() { - base::AutoLock lock(lock_); - queued_queries_.clear(); - destination_ = NULL; + PrinterQueries queries_to_stop; + { + base::AutoLock lock(lock_); + queued_queries_.swap(queries_to_stop); + } + // Stop all pending queries, requests to generate print preview do not have + // corresponding PrintJob, so any pending preview requests are not covered + // by PrintJobManager::StopJobs and should be stopped explicitly. + for (PrinterQueries::iterator itr = queries_to_stop.begin(); + itr != queries_to_stop.end(); ++itr) { + (*itr)->PostTask(FROM_HERE, base::Bind(&PrinterQuery::StopWorker, *itr)); + } } PrintJobManager::PrintJobManager() : is_shutdown_(false) { @@ -72,7 +77,7 @@ PrintJobManager::~PrintJobManager() { scoped_refptr PrintJobManager::queue() { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - if (!queue_) + if (!queue_.get()) queue_ = new PrintQueriesQueue(); return queue_; } @@ -83,7 +88,7 @@ void PrintJobManager::Shutdown() { is_shutdown_ = true; registrar_.RemoveAll(); StopJobs(true); - if (queue_) + if (queue_.get()) queue_->Shutdown(); queue_ = NULL; } diff --git a/chromium_src/chrome/browser/printing/print_job_manager.h b/chromium_src/chrome/browser/printing/print_job_manager.h index 9d03d9a340..ef61541a2e 100644 --- a/chromium_src/chrome/browser/printing/print_job_manager.h +++ b/chromium_src/chrome/browser/printing/print_job_manager.h @@ -10,11 +10,11 @@ #include "base/logging.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" #include "base/threading/non_thread_safe.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" -#include "printing/print_destination_interface.h" namespace printing { @@ -26,9 +26,6 @@ class PrintQueriesQueue : public base::RefCountedThreadSafe { public: PrintQueriesQueue(); - // Sets the print destination to be set on the next print job. - void SetDestination(PrintDestinationInterface* destination); - // Queues a semi-initialized worker thread. Can be called from any thread. // Current use case is queuing from the I/O thread. // TODO(maruel): Have them vanish after a timeout (~5 minutes?) @@ -39,7 +36,8 @@ class PrintQueriesQueue : public base::RefCountedThreadSafe { scoped_refptr PopPrinterQuery(int document_cookie); // Creates new query. - scoped_refptr CreatePrinterQuery(); + scoped_refptr CreatePrinterQuery(int render_process_id, + int render_view_id); void Shutdown(); @@ -54,8 +52,6 @@ class PrintQueriesQueue : public base::RefCountedThreadSafe { PrinterQueries queued_queries_; - scoped_refptr destination_; - DISALLOW_COPY_AND_ASSIGN(PrintQueriesQueue); }; diff --git a/chromium_src/chrome/browser/printing/print_job_worker.cc b/chromium_src/chrome/browser/printing/print_job_worker.cc index a14c87c794..c4794f8154 100644 --- a/chromium_src/chrome/browser/printing/print_job_worker.cc +++ b/chromium_src/chrome/browser/printing/print_job_worker.cc @@ -13,10 +13,10 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/printing/print_job.h" -#include "chrome/browser/printing/printing_ui_web_contents_observer.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_service.h" -#include "grit/generated_resources.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" #include "printing/print_job_constants.h" #include "printing/printed_document.h" #include "printing/printed_page.h" @@ -25,6 +25,8 @@ using content::BrowserThread; +namespace printing { + namespace { // Helper function to ensure |owner| is valid until at least |callback| returns. @@ -33,9 +35,41 @@ void HoldRefCallback(const scoped_refptr& owner, callback.Run(); } -} // namespace +class PrintingContextDelegate : public PrintingContext::Delegate { + public: + PrintingContextDelegate(int render_process_id, int render_view_id); + virtual ~PrintingContextDelegate(); -namespace printing { + virtual gfx::NativeView GetParentView() OVERRIDE; + virtual std::string GetAppLocale() OVERRIDE; + + private: + int render_process_id_; + int render_view_id_; +}; + +PrintingContextDelegate::PrintingContextDelegate(int render_process_id, + int render_view_id) + : render_process_id_(render_process_id), + render_view_id_(render_view_id) { +} + +PrintingContextDelegate::~PrintingContextDelegate() { +} + +gfx::NativeView PrintingContextDelegate::GetParentView() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + content::RenderViewHost* view = + content::RenderViewHost::FromID(render_process_id_, render_view_id_); + if (!view) + return NULL; + content::WebContents* wc = content::WebContents::FromRenderViewHost(view); + return wc ? wc->GetNativeView() : NULL; +} + +std::string PrintingContextDelegate::GetAppLocale() { + return g_browser_process->GetApplicationLocale(); +} void NotificationCallback(PrintJobWorkerOwner* print_job, JobEventDetails::Type detail_type, @@ -49,22 +83,25 @@ void NotificationCallback(PrintJobWorkerOwner* print_job, content::Details(details)); } -PrintJobWorker::PrintJobWorker(PrintJobWorkerOwner* owner) - : Thread("Printing_Worker"), - owner_(owner), - weak_factory_(this) { - // The object is created in the IO thread. - DCHECK_EQ(owner_->message_loop(), base::MessageLoop::current()); +} // namespace - printing_context_.reset(PrintingContext::Create( - g_browser_process->GetApplicationLocale())); +PrintJobWorker::PrintJobWorker(int render_process_id, + int render_view_id, + PrintJobWorkerOwner* owner) + : owner_(owner), thread_("Printing_Worker"), weak_factory_(this) { + // The object is created in the IO thread. + DCHECK(owner_->RunsTasksOnCurrentThread()); + + printing_context_delegate_.reset( + new PrintingContextDelegate(render_process_id, render_view_id)); + printing_context_ = PrintingContext::Create(printing_context_delegate_.get()); } PrintJobWorker::~PrintJobWorker() { // The object is normally deleted in the UI thread, but when the user // cancels printing or in the case of print preview, the worker is destroyed // on the I/O thread. - DCHECK_EQ(owner_->message_loop(), base::MessageLoop::current()); + DCHECK(owner_->RunsTasksOnCurrentThread()); Stop(); } @@ -73,18 +110,12 @@ void PrintJobWorker::SetNewOwner(PrintJobWorkerOwner* new_owner) { owner_ = new_owner; } -void PrintJobWorker::SetPrintDestination( - PrintDestinationInterface* destination) { - destination_ = destination; -} - void PrintJobWorker::GetSettings( bool ask_user_for_settings, - scoped_ptr web_contents_observer, int document_page_count, bool has_selection, MarginType margin_type) { - DCHECK_EQ(message_loop(), base::MessageLoop::current()); + DCHECK(task_runner_->RunsTasksOnCurrentThread()); DCHECK_EQ(page_number_, PageNumber::npos()); // Recursive task processing is needed for the dialog in case it needs to be @@ -97,13 +128,12 @@ void PrintJobWorker::GetSettings( // When we delegate to a destination, we don't ask the user for settings. // TODO(mad): Ask the destination for settings. - if (ask_user_for_settings && destination_.get() == NULL) { + if (ask_user_for_settings) { BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&HoldRefCallback, make_scoped_refptr(owner_), base::Bind(&PrintJobWorker::GetSettingsWithUI, base::Unretained(this), - base::Passed(&web_contents_observer), document_page_count, has_selection))); } else { @@ -116,8 +146,8 @@ void PrintJobWorker::GetSettings( } void PrintJobWorker::SetSettings( - const base::DictionaryValue* const new_settings) { - DCHECK_EQ(message_loop(), base::MessageLoop::current()); + scoped_ptr new_settings) { + DCHECK(task_runner_->RunsTasksOnCurrentThread()); BrowserThread::PostTask( BrowserThread::UI, @@ -126,11 +156,12 @@ void PrintJobWorker::SetSettings( make_scoped_refptr(owner_), base::Bind(&PrintJobWorker::UpdatePrintSettings, base::Unretained(this), - base::Owned(new_settings)))); + base::Passed(&new_settings)))); } void PrintJobWorker::UpdatePrintSettings( - const base::DictionaryValue* const new_settings) { + scoped_ptr new_settings) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); PrintingContext::Result result = printing_context_->UpdatePrintSettings(*new_settings); GetSettingsDone(result); @@ -147,36 +178,31 @@ void PrintJobWorker::GetSettingsDone(PrintingContext::Result result) { // We can't use OnFailure() here since owner_ may not support notifications. // PrintJob will create the new PrintedDocument. - owner_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&PrintJobWorkerOwner::GetSettingsDone, - make_scoped_refptr(owner_), printing_context_->settings(), - result)); + owner_->PostTask(FROM_HERE, + base::Bind(&PrintJobWorkerOwner::GetSettingsDone, + make_scoped_refptr(owner_), + printing_context_->settings(), + result)); } void PrintJobWorker::GetSettingsWithUI( - scoped_ptr web_contents_observer, int document_page_count, bool has_selection) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - - gfx::NativeView parent_view = web_contents_observer->GetParentView(); - if (!parent_view) { - GetSettingsWithUIDone(printing::PrintingContext::FAILED); - return; - } printing_context_->AskUserForSettings( - parent_view, document_page_count, has_selection, + document_page_count, + has_selection, base::Bind(&PrintJobWorker::GetSettingsWithUIDone, base::Unretained(this))); } void PrintJobWorker::GetSettingsWithUIDone(PrintingContext::Result result) { - message_loop()->PostTask( - FROM_HERE, - base::Bind(&HoldRefCallback, make_scoped_refptr(owner_), - base::Bind(&PrintJobWorker::GetSettingsDone, - base::Unretained(this), result))); + PostTask(FROM_HERE, + base::Bind(&HoldRefCallback, + make_scoped_refptr(owner_), + base::Bind(&PrintJobWorker::GetSettingsDone, + base::Unretained(this), + result))); } void PrintJobWorker::UseDefaultSettings() { @@ -185,9 +211,9 @@ void PrintJobWorker::UseDefaultSettings() { } void PrintJobWorker::StartPrinting(PrintedDocument* new_document) { - DCHECK_EQ(message_loop(), base::MessageLoop::current()); + DCHECK(task_runner_->RunsTasksOnCurrentThread()); DCHECK_EQ(page_number_, PageNumber::npos()); - DCHECK_EQ(document_, new_document); + DCHECK_EQ(document_.get(), new_document); DCHECK(document_.get()); if (!document_.get() || page_number_ != PageNumber::npos() || @@ -216,7 +242,7 @@ void PrintJobWorker::StartPrinting(PrintedDocument* new_document) { } void PrintJobWorker::OnDocumentChanged(PrintedDocument* new_document) { - DCHECK_EQ(message_loop(), base::MessageLoop::current()); + DCHECK(task_runner_->RunsTasksOnCurrentThread()); DCHECK_EQ(page_number_, PageNumber::npos()); if (page_number_ != PageNumber::npos()) @@ -230,7 +256,7 @@ void PrintJobWorker::OnNewPage() { return; // message_loop() could return NULL when the print job is cancelled. - DCHECK_EQ(message_loop(), base::MessageLoop::current()); + DCHECK(task_runner_->RunsTasksOnCurrentThread()); if (page_number_ == PageNumber::npos()) { // Find first page to print. @@ -243,15 +269,13 @@ void PrintJobWorker::OnNewPage() { } // We have enough information to initialize page_number_. page_number_.Init(document_->settings(), page_count); - if (destination_.get() != NULL) - destination_->SetPageCount(page_count); } DCHECK_NE(page_number_, PageNumber::npos()); while (true) { // Is the page available? scoped_refptr page = document_->GetPage(page_number_.ToInt()); - if (!page) { + if (!page.get()) { // We need to wait for the page to be available. base::MessageLoop::current()->PostDelayedTask( FROM_HERE, @@ -277,8 +301,33 @@ void PrintJobWorker::Cancel() { // context we run. } +bool PrintJobWorker::IsRunning() const { + return thread_.IsRunning(); +} + +bool PrintJobWorker::PostTask(const tracked_objects::Location& from_here, + const base::Closure& task) { + if (task_runner_.get()) + return task_runner_->PostTask(from_here, task); + return false; +} + +void PrintJobWorker::StopSoon() { + thread_.StopSoon(); +} + +void PrintJobWorker::Stop() { + thread_.Stop(); +} + +bool PrintJobWorker::Start() { + bool result = thread_.Start(); + task_runner_ = thread_.task_runner(); + return result; +} + void PrintJobWorker::OnDocumentDone() { - DCHECK_EQ(message_loop(), base::MessageLoop::current()); + DCHECK(task_runner_->RunsTasksOnCurrentThread()); DCHECK_EQ(page_number_, PageNumber::npos()); DCHECK(document_.get()); @@ -287,24 +336,28 @@ void PrintJobWorker::OnDocumentDone() { return; } - owner_->message_loop()->PostTask( - FROM_HERE, base::Bind(NotificationCallback, make_scoped_refptr(owner_), - JobEventDetails::DOC_DONE, document_, - scoped_refptr())); + owner_->PostTask(FROM_HERE, + base::Bind(&NotificationCallback, + make_scoped_refptr(owner_), + JobEventDetails::DOC_DONE, + document_, + scoped_refptr())); // Makes sure the variables are reinitialized. document_ = NULL; } void PrintJobWorker::SpoolPage(PrintedPage* page) { - DCHECK_EQ(message_loop(), base::MessageLoop::current()); + DCHECK(task_runner_->RunsTasksOnCurrentThread()); DCHECK_NE(page_number_, PageNumber::npos()); // Signal everyone that the page is about to be printed. - owner_->message_loop()->PostTask( - FROM_HERE, base::Bind(NotificationCallback, make_scoped_refptr(owner_), - JobEventDetails::NEW_PAGE, document_, - make_scoped_refptr(page))); + owner_->PostTask(FROM_HERE, + base::Bind(&NotificationCallback, + make_scoped_refptr(owner_), + JobEventDetails::NEW_PAGE, + document_, + make_scoped_refptr(page))); // Preprocess. if (printing_context_->NewPage() != PrintingContext::OK) { @@ -312,18 +365,6 @@ void PrintJobWorker::SpoolPage(PrintedPage* page) { return; } - if (destination_.get() != NULL) { - std::vector metabytes(page->metafile()->GetDataSize()); - bool success = page->metafile()->GetData( - reinterpret_cast(&metabytes[0]), metabytes.size()); - DCHECK(success) << "Failed to get metafile data."; - destination_->SetPageContent( - page->page_number(), - reinterpret_cast(&metabytes[0]), - metabytes.size()); - return; - } - // Actual printing. #if defined(OS_WIN) || defined(OS_MACOSX) document_->RenderPrintedPage(*page, printing_context_->context()); @@ -338,23 +379,26 @@ void PrintJobWorker::SpoolPage(PrintedPage* page) { } // Signal everyone that the page is printed. - owner_->message_loop()->PostTask( - FROM_HERE, - base::Bind(NotificationCallback, make_scoped_refptr(owner_), - JobEventDetails::PAGE_DONE, document_, - make_scoped_refptr(page))); + owner_->PostTask(FROM_HERE, + base::Bind(&NotificationCallback, + make_scoped_refptr(owner_), + JobEventDetails::PAGE_DONE, + document_, + make_scoped_refptr(page))); } void PrintJobWorker::OnFailure() { - DCHECK_EQ(message_loop(), base::MessageLoop::current()); + DCHECK(task_runner_->RunsTasksOnCurrentThread()); // We may loose our last reference by broadcasting the FAILED event. scoped_refptr handle(owner_); - owner_->message_loop()->PostTask( - FROM_HERE, base::Bind(NotificationCallback, make_scoped_refptr(owner_), - JobEventDetails::FAILED, document_, - scoped_refptr())); + owner_->PostTask(FROM_HERE, + base::Bind(&NotificationCallback, + make_scoped_refptr(owner_), + JobEventDetails::FAILED, + document_, + scoped_refptr())); Cancel(); // Makes sure the variables are reinitialized. diff --git a/chromium_src/chrome/browser/printing/print_job_worker.h b/chromium_src/chrome/browser/printing/print_job_worker.h index 2ce01f081a..a8378bb235 100644 --- a/chromium_src/chrome/browser/printing/print_job_worker.h +++ b/chromium_src/chrome/browser/printing/print_job_worker.h @@ -9,12 +9,10 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread.h" +#include "content/public/browser/browser_thread.h" #include "printing/page_number.h" -#include "printing/print_destination_interface.h" -#include "printing/printing_context.h" #include "printing/print_job_constants.h" - -class PrintingUIWebContentsObserver; +#include "printing/printing_context.h" namespace base { class DictionaryValue; @@ -22,39 +20,35 @@ class DictionaryValue; namespace printing { -class PrintedDocument; -class PrintedPage; class PrintJob; class PrintJobWorkerOwner; +class PrintedDocument; +class PrintedPage; // Worker thread code. It manages the PrintingContext, which can be blocking // and/or run a message loop. This is the object that generates most // NOTIFY_PRINT_JOB_EVENT notifications, but they are generated through a // NotificationTask task to be executed from the right thread, the UI thread. // PrintJob always outlives its worker instance. -class PrintJobWorker : public base::Thread { +class PrintJobWorker { public: - explicit PrintJobWorker(PrintJobWorkerOwner* owner); + PrintJobWorker(int render_process_id, + int render_view_id, + PrintJobWorkerOwner* owner); virtual ~PrintJobWorker(); void SetNewOwner(PrintJobWorkerOwner* new_owner); - // Set a destination for print. - // This supercedes the document's rendering destination. - void SetPrintDestination(PrintDestinationInterface* destination); - // Initializes the print settings. If |ask_user_for_settings| is true, a // Print... dialog box will be shown to ask the user his preference. void GetSettings( bool ask_user_for_settings, - scoped_ptr web_contents_observer, int document_page_count, bool has_selection, MarginType margin_type); - // Set the new print settings. This function takes ownership of - // |new_settings|. - void SetSettings(const base::DictionaryValue* const new_settings); + // Set the new print settings. + void SetSettings(scoped_ptr new_settings); // Starts the printing loop. Every pages are printed as soon as the data is // available. Makes sure the new_document is the right one. @@ -71,6 +65,22 @@ class PrintJobWorker : public base::Thread { // This is the only function that can be called in a thread. void Cancel(); + // Returns true if the thread has been started, and not yet stopped. + bool IsRunning() const; + + // Posts the given task to be run. + bool PostTask(const tracked_objects::Location& from_here, + const base::Closure& task); + + // Signals the thread to exit in the near future. + void StopSoon(); + + // Signals the thread to exit and returns once the thread has exited. + void Stop(); + + // Starts the thread. + bool Start(); + protected: // Retrieves the context for testing only. PrintingContext* printing_context() { return printing_context_.get(); } @@ -97,7 +107,6 @@ class PrintJobWorker : public base::Thread { // Required on Mac and Linux. Windows can display UI from non-main threads, // but sticks with this for consistency. void GetSettingsWithUI( - scoped_ptr web_contents_observer, int document_page_count, bool has_selection); @@ -106,9 +115,8 @@ class PrintJobWorker : public base::Thread { // back into the IO thread for GetSettingsDone(). void GetSettingsWithUIDone(PrintingContext::Result result); - // Called on the UI thread to update the print settings. This function takes - // the ownership of |new_settings|. - void UpdatePrintSettings(const base::DictionaryValue* const new_settings); + // Called on the UI thread to update the print settings. + void UpdatePrintSettings(scoped_ptr new_settings); // Reports settings back to owner_. void GetSettingsDone(PrintingContext::Result result); @@ -118,15 +126,15 @@ class PrintJobWorker : public base::Thread { // systems. void UseDefaultSettings(); + // Printing context delegate. + scoped_ptr printing_context_delegate_; + // Information about the printer setting. scoped_ptr printing_context_; // The printed document. Only has read-only access. scoped_refptr document_; - // The print destination, may be NULL. - scoped_refptr destination_; - // The print job owning this worker thread. It is guaranteed to outlive this // object. PrintJobWorkerOwner* owner_; @@ -134,6 +142,12 @@ class PrintJobWorker : public base::Thread { // Current page number to print. PageNumber page_number_; + // Thread to run worker tasks. + base::Thread thread_; + + // Tread-safe pointer to task runner of the |thread_|. + scoped_refptr task_runner_; + // Used to generate a WeakPtr for callbacks. base::WeakPtrFactory weak_factory_; diff --git a/chromium_src/chrome/browser/printing/print_job_worker_owner.cc b/chromium_src/chrome/browser/printing/print_job_worker_owner.cc new file mode 100644 index 0000000000..843ab4616d --- /dev/null +++ b/chromium_src/chrome/browser/printing/print_job_worker_owner.cc @@ -0,0 +1,27 @@ +// 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. + +#include "chrome/browser/printing/print_job_worker_owner.h" + +#include "base/message_loop/message_loop.h" + +namespace printing { + +PrintJobWorkerOwner::PrintJobWorkerOwner() + : task_runner_(base::MessageLoop::current()->task_runner()) { +} + +PrintJobWorkerOwner::~PrintJobWorkerOwner() { +} + +bool PrintJobWorkerOwner::RunsTasksOnCurrentThread() const { + return task_runner_->RunsTasksOnCurrentThread(); +} + +bool PrintJobWorkerOwner::PostTask(const tracked_objects::Location& from_here, + const base::Closure& task) { + return task_runner_->PostTask(from_here, task); +} + +} // namespace printing diff --git a/chromium_src/chrome/browser/printing/print_job_worker_owner.h b/chromium_src/chrome/browser/printing/print_job_worker_owner.h index 8f9f58509f..00a561a39b 100644 --- a/chromium_src/chrome/browser/printing/print_job_worker_owner.h +++ b/chromium_src/chrome/browser/printing/print_job_worker_owner.h @@ -10,8 +10,12 @@ namespace base { class MessageLoop; +class SequencedTaskRunner; } +namespace tracked_objects { +class Location; +} namespace printing { @@ -21,6 +25,8 @@ class PrintSettings; class PrintJobWorkerOwner : public base::RefCountedThreadSafe { public: + PrintJobWorkerOwner(); + // Finishes the initialization began by PrintJobWorker::GetSettings(). // Creates a new PrintedDocument if necessary. Solely meant to be called by // PrintJobWorker. @@ -30,19 +36,29 @@ class PrintJobWorkerOwner // Detach the PrintJobWorker associated to this object. virtual PrintJobWorker* DetachWorker(PrintJobWorkerOwner* new_owner) = 0; - // Retrieves the message loop that is expected to process GetSettingsDone. - virtual base::MessageLoop* message_loop() = 0; - // Access the current settings. virtual const PrintSettings& settings() const = 0; // Cookie uniquely identifying the PrintedDocument and/or loaded settings. virtual int cookie() const = 0; + // Returns true if the current thread is a thread on which a task + // may be run, and false if no task will be run on the current + // thread. + bool RunsTasksOnCurrentThread() const; + + // Posts the given task to be run. + bool PostTask(const tracked_objects::Location& from_here, + const base::Closure& task); + protected: friend class base::RefCountedThreadSafe; - virtual ~PrintJobWorkerOwner() {} + virtual ~PrintJobWorkerOwner(); + + // Task runner reference. Used to send notifications in the right + // thread. + scoped_refptr task_runner_; }; } // namespace printing diff --git a/chromium_src/chrome/browser/printing/print_view_manager_base.cc b/chromium_src/chrome/browser/printing/print_view_manager_base.cc index db77791ba7..e2cfedd4a2 100644 --- a/chromium_src/chrome/browser/printing/print_view_manager_base.cc +++ b/chromium_src/chrome/browser/printing/print_view_manager_base.cc @@ -24,11 +24,14 @@ #include "content/public/browser/notification_source.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" -#include "grit/generated_resources.h" -#include "printing/metafile_impl.h" +#include "printing/pdf_metafile_skia.h" #include "printing/printed_document.h" #include "ui/base/l10n/l10n_util.h" +#if defined(ENABLE_FULL_PRINTING) +#include "chrome/browser/printing/print_error_dialog.h" +#endif + using base::TimeDelta; using content::BrowserThread; @@ -36,11 +39,6 @@ namespace printing { namespace { -#if defined(OS_WIN) && !defined(WIN_PDF_METAFILE_FOR_PRINTING) -// Limits memory usage by raster to 64 MiB. -const int kMaxRasterSizeInPixels = 16*1024*1024; -#endif - } // namespace PrintViewManagerBase::PrintViewManagerBase(content::WebContents* web_contents) @@ -50,11 +48,10 @@ PrintViewManagerBase::PrintViewManagerBase(content::WebContents* web_contents) inside_inner_message_loop_(false), cookie_(0), queue_(g_browser_process->print_job_manager()->queue()) { - DCHECK(queue_); -#if (defined(OS_POSIX) && !defined(OS_MACOSX)) || \ - defined(WIN_PDF_METAFILE_FOR_PRINTING) + DCHECK(queue_.get()); +#if !defined(OS_MACOSX) expecting_first_page_ = true; -#endif +#endif // OS_MACOSX printing_enabled_ = true; } @@ -63,10 +60,12 @@ PrintViewManagerBase::~PrintViewManagerBase() { DisconnectFromCurrentPrintJob(); } +#if !defined(DISABLE_BASIC_PRINTING) bool PrintViewManagerBase::PrintNow(bool silent, bool print_background) { return PrintNowInternal(new PrintMsg_PrintPages( routing_id(), silent, print_background)); } +#endif // !DISABLE_BASIC_PRINTING void PrintViewManagerBase::NavigationStopped() { // Cancel the current job, wait for the worker to finish. @@ -117,13 +116,12 @@ void PrintViewManagerBase::OnDidPrintPage( return; } -#if (defined(OS_WIN) && !defined(WIN_PDF_METAFILE_FOR_PRINTING)) || \ - defined(OS_MACOSX) +#if defined(OS_MACOSX) const bool metafile_must_be_valid = true; -#elif defined(OS_POSIX) || defined(WIN_PDF_METAFILE_FOR_PRINTING) +#else const bool metafile_must_be_valid = expecting_first_page_; expecting_first_page_ = false; -#endif +#endif // OS_MACOSX base::SharedMemory shared_buf(params.metafile_data_handle, true); if (metafile_must_be_valid) { @@ -134,7 +132,7 @@ void PrintViewManagerBase::OnDidPrintPage( } } - scoped_ptr metafile(new NativeMetafile); + scoped_ptr metafile(new PdfMetafileSkia); if (metafile_must_be_valid) { if (!metafile->InitFromData(shared_buf.memory(), params.data_size)) { NOTREACHED() << "Invalid metafile header"; @@ -143,32 +141,10 @@ void PrintViewManagerBase::OnDidPrintPage( } } -#if defined(OS_WIN) && !defined(WIN_PDF_METAFILE_FOR_PRINTING) - bool big_emf = (params.data_size && params.data_size >= kMetafileMaxSize); - int raster_size = - std::min(params.page_size.GetArea(), kMaxRasterSizeInPixels); - if (big_emf) { - scoped_ptr raster_metafile( - metafile->RasterizeMetafile(raster_size)); - if (raster_metafile.get()) { - metafile.swap(raster_metafile); - } else if (big_emf) { - // Don't fall back to emf here. - NOTREACHED() << "size:" << params.data_size; - TerminatePrintJob(true); - web_contents()->Stop(); - return; - } - } -#endif // OS_WIN && !WIN_PDF_METAFILE_FOR_PRINTING - -#if !defined(WIN_PDF_METAFILE_FOR_PRINTING) +#if !defined(OS_WIN) // Update the rendered document. It will send notifications to the listener. document->SetPage(params.page_number, - metafile.release(), -#if defined(OS_WIN) - params.actual_shrink, -#endif // OS_WIN + metafile.PassAs(), params.page_size, params.content_area); @@ -180,19 +156,8 @@ void PrintViewManagerBase::OnDidPrintPage( params.data_size); document->DebugDumpData(bytes, FILE_PATH_LITERAL(".pdf")); - - if (!pdf_to_emf_converter_) - pdf_to_emf_converter_ = PdfToEmfConverter::CreateDefault(); - - const int kPrinterDpi = print_job_->settings().dpi(); - pdf_to_emf_converter_->Start( - bytes, - printing::PdfRenderSettings(params.content_area, kPrinterDpi, true), - base::Bind(&PrintViewManagerBase::OnPdfToEmfConverted, - base::Unretained(this), - params)); } -#endif // !WIN_PDF_METAFILE_FOR_PRINTING +#endif // !OS_WIN } void PrintViewManagerBase::OnPrintingFailed(int cookie) { @@ -386,10 +351,9 @@ void PrintViewManagerBase::DisconnectFromCurrentPrintJob() { // DO NOT wait for the job to finish. ReleasePrintJob(); } -#if (defined(OS_POSIX) && !defined(OS_MACOSX)) || \ - defined(WIN_PDF_METAFILE_FOR_PRINTING) +#if !defined(OS_MACOSX) expecting_first_page_ = true; -#endif +#endif // OS_MACOSX } void PrintViewManagerBase::PrintingDone(bool success) { @@ -481,12 +445,12 @@ bool PrintViewManagerBase::OpportunisticallyCreatePrintJob(int cookie) { // The job was initiated by a script. Time to get the corresponding worker // thread. scoped_refptr queued_query = queue_->PopPrinterQuery(cookie); - if (!queued_query) { + if (!queued_query.get()) { NOTREACHED(); return false; } - if (!CreateNewPrintJob(queued_query)) { + if (!CreateNewPrintJob(queued_query.get())) { // Don't kill anything. return false; } @@ -512,8 +476,6 @@ void PrintViewManagerBase::ReleasePrinterQuery() { int cookie = cookie_; cookie_ = 0; - queue_->SetDestination(NULL); - printing::PrintJobManager* print_job_manager = g_browser_process->print_job_manager(); @@ -523,7 +485,7 @@ void PrintViewManagerBase::ReleasePrinterQuery() { scoped_refptr printer_query; printer_query = queue_->PopPrinterQuery(cookie); - if (!printer_query) + if (!printer_query.get()) return; BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, diff --git a/chromium_src/chrome/browser/printing/print_view_manager_base.h b/chromium_src/chrome/browser/printing/print_view_manager_base.h index 61b0fd4400..f9232fdfe8 100644 --- a/chromium_src/chrome/browser/printing/print_view_manager_base.h +++ b/chromium_src/chrome/browser/printing/print_view_manager_base.h @@ -23,7 +23,7 @@ class RenderViewHost; namespace printing { class JobEventDetails; -class PdfToEmfConverter; +class MetafilePlayer; class PrintJob; class PrintJobWorkerOwner; class PrintQueriesQueue; @@ -35,10 +35,12 @@ class PrintViewManagerBase : public content::NotificationObserver, public: virtual ~PrintViewManagerBase(); +#if !defined(DISABLE_BASIC_PRINTING) // Prints the current document immediately. Since the rendering is // asynchronous, the actual printing will not be completed on the return of // this function. Returns false if printing is impossible at the moment. virtual bool PrintNow(bool silent, bool print_background); +#endif // !DISABLE_BASIC_PRINTING // PrintedPagesSource implementation. virtual base::string16 RenderSourceName() OVERRIDE; @@ -140,11 +142,10 @@ class PrintViewManagerBase : public content::NotificationObserver, // print settings are being loaded. bool inside_inner_message_loop_; -#if (defined(OS_POSIX) && !defined(OS_MACOSX)) || \ - defined(WIN_PDF_METAFILE_FOR_PRINTING) +#if !defined(OS_MACOSX) // Set to true when OnDidPrintPage() should be expecting the first page. bool expecting_first_page_; -#endif +#endif // OS_MACOSX // The document cookie of the current PrinterQuery. int cookie_; diff --git a/chromium_src/chrome/browser/printing/printer_query.cc b/chromium_src/chrome/browser/printing/printer_query.cc index 6770e575c6..6cd11ff067 100644 --- a/chromium_src/chrome/browser/printing/printer_query.cc +++ b/chromium_src/chrome/browser/printing/printer_query.cc @@ -10,13 +10,11 @@ #include "base/threading/thread_restrictions.h" #include "base/values.h" #include "chrome/browser/printing/print_job_worker.h" -#include "chrome/browser/printing/printing_ui_web_contents_observer.h" namespace printing { -PrinterQuery::PrinterQuery() - : io_message_loop_(base::MessageLoop::current()), - worker_(new PrintJobWorker(this)), +PrinterQuery::PrinterQuery(int render_process_id, int render_view_id) + : worker_(new PrintJobWorker(render_process_id, render_view_id, this)), is_print_dialog_box_shown_(false), cookie_(PrintSettings::NewCookie()), last_status_(PrintingContext::FAILED) { @@ -57,10 +55,6 @@ PrintJobWorker* PrinterQuery::DetachWorker(PrintJobWorkerOwner* new_owner) { return worker_.release(); } -base::MessageLoop* PrinterQuery::message_loop() { - return io_message_loop_; -} - const PrintSettings& PrinterQuery::settings() const { return settings_; } @@ -71,43 +65,34 @@ int PrinterQuery::cookie() const { void PrinterQuery::GetSettings( GetSettingsAskParam ask_user_for_settings, - scoped_ptr web_contents_observer, int expected_page_count, bool has_selection, MarginType margin_type, const base::Closure& callback) { - DCHECK_EQ(io_message_loop_, base::MessageLoop::current()); + DCHECK(RunsTasksOnCurrentThread()); DCHECK(!is_print_dialog_box_shown_); StartWorker(callback); // Real work is done in PrintJobWorker::GetSettings(). is_print_dialog_box_shown_ = ask_user_for_settings == ASK_USER; - worker_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&PrintJobWorker::GetSettings, - base::Unretained(worker_.get()), - is_print_dialog_box_shown_, - base::Passed(&web_contents_observer), - expected_page_count, - has_selection, - margin_type)); + worker_->PostTask(FROM_HERE, + base::Bind(&PrintJobWorker::GetSettings, + base::Unretained(worker_.get()), + is_print_dialog_box_shown_, + expected_page_count, + has_selection, + margin_type)); } -void PrinterQuery::SetSettings(const base::DictionaryValue& new_settings, +void PrinterQuery::SetSettings(scoped_ptr new_settings, const base::Closure& callback) { StartWorker(callback); - worker_->message_loop()->PostTask( - FROM_HERE, - base::Bind(&PrintJobWorker::SetSettings, - base::Unretained(worker_.get()), - new_settings.DeepCopy())); -} - -void PrinterQuery::SetWorkerDestination( - PrintDestinationInterface* destination) { - worker_->SetPrintDestination(destination); + worker_->PostTask(FROM_HERE, + base::Bind(&PrintJobWorker::SetSettings, + base::Unretained(worker_.get()), + base::Passed(&new_settings))); } void PrinterQuery::StartWorker(const base::Closure& callback) { @@ -115,7 +100,7 @@ void PrinterQuery::StartWorker(const base::Closure& callback) { DCHECK(worker_.get()); // Lazily create the worker thread. There is one worker thread per print job. - if (!worker_->message_loop()) + if (!worker_->IsRunning()) worker_->Start(); callback_ = callback; diff --git a/chromium_src/chrome/browser/printing/printer_query.h b/chromium_src/chrome/browser/printing/printer_query.h index aab4914324..22af08d7af 100644 --- a/chromium_src/chrome/browser/printing/printer_query.h +++ b/chromium_src/chrome/browser/printing/printer_query.h @@ -11,11 +11,8 @@ #include "chrome/browser/printing/print_job_worker_owner.h" #include "printing/print_job_constants.h" -class PrintingUIWebContentsObserver; - namespace base { class DictionaryValue; -class MessageLoop; } namespace printing { @@ -32,13 +29,12 @@ class PrinterQuery : public PrintJobWorkerOwner { ASK_USER, }; - PrinterQuery(); + PrinterQuery(int render_process_id, int render_view_id); // PrintJobWorkerOwner implementation. virtual void GetSettingsDone(const PrintSettings& new_settings, PrintingContext::Result result) OVERRIDE; virtual PrintJobWorker* DetachWorker(PrintJobWorkerOwner* new_owner) OVERRIDE; - virtual base::MessageLoop* message_loop() OVERRIDE; virtual const PrintSettings& settings() const OVERRIDE; virtual int cookie() const OVERRIDE; @@ -48,19 +44,15 @@ class PrinterQuery : public PrintJobWorkerOwner { // |ask_for_user_settings| is DEFAULTS. void GetSettings( GetSettingsAskParam ask_user_for_settings, - scoped_ptr web_contents_observer, int expected_page_count, bool has_selection, MarginType margin_type, const base::Closure& callback); // Updates the current settings with |new_settings| dictionary values. - void SetSettings(const base::DictionaryValue& new_settings, + void SetSettings(scoped_ptr new_settings, const base::Closure& callback); - // Set a destination for the worker. - void SetWorkerDestination(PrintDestinationInterface* destination); - // Stops the worker thread since the client is done with this object. void StopWorker(); @@ -78,10 +70,6 @@ class PrinterQuery : public PrintJobWorkerOwner { // Lazy create the worker thread. There is one worker thread per print job. void StartWorker(const base::Closure& callback); - // Main message loop reference. Used to send notifications in the right - // thread. - base::MessageLoop* const io_message_loop_; - // All the UI is done in a worker thread because many Win32 print functions // are blocking and enters a message loop without your consent. There is one // worker thread per print job. diff --git a/chromium_src/chrome/browser/printing/printing_message_filter.cc b/chromium_src/chrome/browser/printing/printing_message_filter.cc index d10843fe3c..15ca50fba5 100644 --- a/chromium_src/chrome/browser/printing/printing_message_filter.cc +++ b/chromium_src/chrome/browser/printing/printing_message_filter.cc @@ -8,21 +8,56 @@ #include "base/bind.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/printing/printer_query.h" #include "chrome/browser/printing/print_job_manager.h" -#include "chrome/browser/printing/printing_ui_web_contents_observer.h" +#include "chrome/browser/printing/printer_query.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_io_data.h" #include "chrome/common/print_messages.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/child_process_host.h" + +#if defined(ENABLE_FULL_PRINTING) +#include "chrome/browser/ui/webui/print_preview/print_preview_ui.h" +#endif + +#if defined(OS_CHROMEOS) +#include + +#include + +#include "base/files/file_util.h" +#include "base/lazy_instance.h" +#include "chrome/browser/printing/print_dialog_cloud.h" +#endif + +#if defined(OS_ANDROID) +#include "base/strings/string_number_conversions.h" +#include "chrome/browser/printing/print_view_manager_basic.h" +#include "printing/printing_context_android.h" +#endif using content::BrowserThread; +namespace printing { + namespace { -void RenderParamsFromPrintSettings(const printing::PrintSettings& settings, +#if defined(OS_CHROMEOS) +typedef std::map SequenceToPathMap; + +struct PrintingSequencePathMap { + SequenceToPathMap map; + int sequence; +}; + +// No locking, only access on the FILE thread. +static base::LazyInstance + g_printing_file_descriptor_map = LAZY_INSTANCE_INITIALIZER; +#endif + +void RenderParamsFromPrintSettings(const PrintSettings& settings, PrintMsg_Print_Params* params) { params->page_size = settings.page_setup_device_units().physical_size(); params->content_size.SetSize( @@ -57,21 +92,45 @@ PrintingMessageFilter::PrintingMessageFilter(int render_process_id) : BrowserMessageFilter(PrintMsgStart), render_process_id_(render_process_id), queue_(g_browser_process->print_job_manager()->queue()) { - DCHECK(queue_); + DCHECK(queue_.get()); } PrintingMessageFilter::~PrintingMessageFilter() { } +void PrintingMessageFilter::OverrideThreadForMessage( + const IPC::Message& message, BrowserThread::ID* thread) { +#if defined(OS_CHROMEOS) + if (message.type() == PrintHostMsg_AllocateTempFileForPrinting::ID || + message.type() == PrintHostMsg_TempFileForPrintingWritten::ID) { + *thread = BrowserThread::FILE; + } +#elif defined(OS_ANDROID) + if (message.type() == PrintHostMsg_AllocateTempFileForPrinting::ID || + message.type() == PrintHostMsg_TempFileForPrintingWritten::ID) { + *thread = BrowserThread::UI; + } +#endif +} + bool PrintingMessageFilter::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(PrintingMessageFilter, message) #if defined(OS_WIN) IPC_MESSAGE_HANDLER(PrintHostMsg_DuplicateSection, OnDuplicateSection) +#endif +#if defined(OS_CHROMEOS) || defined(OS_ANDROID) + IPC_MESSAGE_HANDLER(PrintHostMsg_AllocateTempFileForPrinting, + OnAllocateTempFileForPrinting) + IPC_MESSAGE_HANDLER(PrintHostMsg_TempFileForPrintingWritten, + OnTempFileForPrintingWritten) #endif IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_GetDefaultPrintSettings, OnGetDefaultPrintSettings) IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_ScriptedPrint, OnScriptedPrint) +#if defined(ENABLE_FULL_PRINTING) + IPC_MESSAGE_HANDLER(PrintHostMsg_CheckForCancel, OnCheckForCancel) +#endif IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -88,6 +147,102 @@ void PrintingMessageFilter::OnDuplicateSection( } #endif +#if defined(OS_CHROMEOS) || defined(OS_ANDROID) +void PrintingMessageFilter::OnAllocateTempFileForPrinting( + int render_view_id, + base::FileDescriptor* temp_file_fd, + int* sequence_number) { +#if defined(OS_CHROMEOS) + // TODO(thestig): Use |render_view_id| for Chrome OS. + DCHECK_CURRENTLY_ON(BrowserThread::FILE); + temp_file_fd->fd = *sequence_number = -1; + temp_file_fd->auto_close = false; + + SequenceToPathMap* map = &g_printing_file_descriptor_map.Get().map; + *sequence_number = g_printing_file_descriptor_map.Get().sequence++; + + base::FilePath path; + if (base::CreateTemporaryFile(&path)) { + int fd = open(path.value().c_str(), O_WRONLY); + if (fd >= 0) { + SequenceToPathMap::iterator it = map->find(*sequence_number); + if (it != map->end()) { + NOTREACHED() << "Sequence number already in use. seq=" << + *sequence_number; + } else { + (*map)[*sequence_number] = path; + temp_file_fd->fd = fd; + temp_file_fd->auto_close = true; + } + } + } +#elif defined(OS_ANDROID) + DCHECK_CURRENTLY_ON(BrowserThread::UI); + content::WebContents* wc = GetWebContentsForRenderView(render_view_id); + if (!wc) + return; + PrintViewManagerBasic* print_view_manager = + PrintViewManagerBasic::FromWebContents(wc); + // The file descriptor is originally created in & passed from the Android + // side, and it will handle the closing. + const base::FileDescriptor& file_descriptor = + print_view_manager->file_descriptor(); + temp_file_fd->fd = file_descriptor.fd; + temp_file_fd->auto_close = false; +#endif +} + +void PrintingMessageFilter::OnTempFileForPrintingWritten(int render_view_id, + int sequence_number) { +#if defined(OS_CHROMEOS) + DCHECK_CURRENTLY_ON(BrowserThread::FILE); + SequenceToPathMap* map = &g_printing_file_descriptor_map.Get().map; + SequenceToPathMap::iterator it = map->find(sequence_number); + if (it == map->end()) { + NOTREACHED() << "Got a sequence that we didn't pass to the " + "renderer: " << sequence_number; + return; + } + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&PrintingMessageFilter::CreatePrintDialogForFile, + this, render_view_id, it->second)); + + // Erase the entry in the map. + map->erase(it); +#elif defined(OS_ANDROID) + DCHECK_CURRENTLY_ON(BrowserThread::UI); + content::WebContents* wc = GetWebContentsForRenderView(render_view_id); + if (!wc) + return; + PrintViewManagerBasic* print_view_manager = + PrintViewManagerBasic::FromWebContents(wc); + const base::FileDescriptor& file_descriptor = + print_view_manager->file_descriptor(); + PrintingContextAndroid::PdfWritingDone(file_descriptor.fd, true); + // Invalidate the file descriptor so it doesn't accidentally get reused. + print_view_manager->set_file_descriptor(base::FileDescriptor(-1, false)); +#endif +} +#endif // defined(OS_CHROMEOS) || defined(OS_ANDROID) + +#if defined(OS_CHROMEOS) +void PrintingMessageFilter::CreatePrintDialogForFile( + int render_view_id, + const base::FilePath& path) { + content::WebContents* wc = GetWebContentsForRenderView(render_view_id); + if (!wc) + return; + print_dialog_cloud::CreatePrintDialogForFile( + wc->GetBrowserContext(), + wc->GetTopLevelNativeWindow(), + path, + wc->GetTitle(), + base::string16(), + std::string("application/pdf")); +} +#endif // defined(OS_CHROMEOS) + content::WebContents* PrintingMessageFilter::GetWebContentsForRenderView( int render_view_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -96,80 +251,41 @@ content::WebContents* PrintingMessageFilter::GetWebContentsForRenderView( return view ? content::WebContents::FromRenderViewHost(view) : NULL; } -struct PrintingMessageFilter::GetPrintSettingsForRenderViewParams { - printing::PrinterQuery::GetSettingsAskParam ask_user_for_settings; - int expected_page_count; - bool has_selection; - printing::MarginType margin_type; -}; - -void PrintingMessageFilter::GetPrintSettingsForRenderView( - int render_view_id, - GetPrintSettingsForRenderViewParams params, - const base::Closure& callback, - scoped_refptr printer_query) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - content::WebContents* wc = GetWebContentsForRenderView(render_view_id); - if (wc) { - scoped_ptr wc_observer( - new PrintingUIWebContentsObserver(wc)); - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&printing::PrinterQuery::GetSettings, printer_query, - params.ask_user_for_settings, base::Passed(&wc_observer), - params.expected_page_count, params.has_selection, - params.margin_type, callback)); - } else { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&PrintingMessageFilter::OnGetPrintSettingsFailed, this, - callback, printer_query)); - } -} - -void PrintingMessageFilter::OnGetPrintSettingsFailed( - const base::Closure& callback, - scoped_refptr printer_query) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - printer_query->GetSettingsDone(printing::PrintSettings(), - printing::PrintingContext::FAILED); - callback.Run(); -} - void PrintingMessageFilter::OnGetDefaultPrintSettings(IPC::Message* reply_msg) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - scoped_refptr printer_query; - if (false) { + scoped_refptr printer_query; +#if 0 + if (!profile_io_data_->printing_enabled()->GetValue()) { // Reply with NULL query. OnGetDefaultPrintSettingsReply(printer_query, reply_msg); return; } +#endif printer_query = queue_->PopPrinterQuery(0); - if (!printer_query) - printer_query = queue_->CreatePrinterQuery(); + if (!printer_query.get()) { + printer_query = + queue_->CreatePrinterQuery(render_process_id_, reply_msg->routing_id()); + } // Loads default settings. This is asynchronous, only the IPC message sender // will hang until the settings are retrieved. - GetPrintSettingsForRenderViewParams params; - params.ask_user_for_settings = printing::PrinterQuery::DEFAULTS; - params.expected_page_count = 0; - params.has_selection = false; - params.margin_type = printing::DEFAULT_MARGINS; - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&PrintingMessageFilter::GetPrintSettingsForRenderView, this, - reply_msg->routing_id(), params, - base::Bind(&PrintingMessageFilter::OnGetDefaultPrintSettingsReply, - this, printer_query, reply_msg), - printer_query)); + printer_query->GetSettings( + PrinterQuery::DEFAULTS, + 0, + false, + DEFAULT_MARGINS, + base::Bind(&PrintingMessageFilter::OnGetDefaultPrintSettingsReply, + this, + printer_query, + reply_msg)); } void PrintingMessageFilter::OnGetDefaultPrintSettingsReply( - scoped_refptr printer_query, + scoped_refptr printer_query, IPC::Message* reply_msg) { PrintMsg_Print_Params params; if (!printer_query.get() || - printer_query->last_status() != printing::PrintingContext::OK) { + printer_query->last_status() != PrintingContext::OK) { params.Reset(); } else { RenderParamsFromPrintSettings(printer_query->settings(), ¶ms); @@ -191,43 +307,69 @@ void PrintingMessageFilter::OnGetDefaultPrintSettingsReply( void PrintingMessageFilter::OnScriptedPrint( const PrintHostMsg_ScriptedPrint_Params& params, IPC::Message* reply_msg) { - scoped_refptr printer_query = + scoped_refptr printer_query = queue_->PopPrinterQuery(params.cookie); - if (!printer_query) - printer_query = queue_->CreatePrinterQuery(); - GetPrintSettingsForRenderViewParams settings_params; - settings_params.ask_user_for_settings = printing::PrinterQuery::ASK_USER; - settings_params.expected_page_count = params.expected_pages_count; - settings_params.has_selection = params.has_selection; - settings_params.margin_type = params.margin_type; - - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&PrintingMessageFilter::GetPrintSettingsForRenderView, this, - reply_msg->routing_id(), settings_params, - base::Bind(&PrintingMessageFilter::OnScriptedPrintReply, this, - printer_query, reply_msg), - printer_query)); + if (!printer_query.get()) { + printer_query = + queue_->CreatePrinterQuery(render_process_id_, reply_msg->routing_id()); + } + printer_query->GetSettings( + PrinterQuery::ASK_USER, + params.expected_pages_count, + params.has_selection, + params.margin_type, + base::Bind(&PrintingMessageFilter::OnScriptedPrintReply, + this, + printer_query, + reply_msg)); } void PrintingMessageFilter::OnScriptedPrintReply( - scoped_refptr printer_query, + scoped_refptr printer_query, IPC::Message* reply_msg) { PrintMsg_PrintPages_Params params; - if (printer_query->last_status() != printing::PrintingContext::OK || +#if defined(OS_ANDROID) + // We need to save the routing ID here because Send method below deletes the + // |reply_msg| before we can get the routing ID for the Android code. + int routing_id = reply_msg->routing_id(); +#endif + if (printer_query->last_status() != PrintingContext::OK || !printer_query->settings().dpi()) { params.Reset(); } else { RenderParamsFromPrintSettings(printer_query->settings(), ¶ms.params); params.params.document_cookie = printer_query->cookie(); - params.pages = - printing::PageRange::GetPages(printer_query->settings().ranges()); + params.pages = PageRange::GetPages(printer_query->settings().ranges()); } PrintHostMsg_ScriptedPrint::WriteReplyParams(reply_msg, params); Send(reply_msg); if (params.params.dpi && params.params.document_cookie) { +#if defined(OS_ANDROID) + int file_descriptor; + const base::string16& device_name = printer_query->settings().device_name(); + if (base::StringToInt(device_name, &file_descriptor)) { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&PrintingMessageFilter::UpdateFileDescriptor, this, + routing_id, file_descriptor)); + } +#endif queue_->QueuePrinterQuery(printer_query.get()); } else { printer_query->StopWorker(); } } + +#if defined(OS_ANDROID) +void PrintingMessageFilter::UpdateFileDescriptor(int render_view_id, int fd) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + content::WebContents* wc = GetWebContentsForRenderView(render_view_id); + if (!wc) + return; + PrintViewManagerBasic* print_view_manager = + PrintViewManagerBasic::FromWebContents(wc); + print_view_manager->set_file_descriptor(base::FileDescriptor(fd, false)); +} +#endif + +} // namespace printing diff --git a/chromium_src/chrome/browser/printing/printing_message_filter.h b/chromium_src/chrome/browser/printing/printing_message_filter.h index 8a9d9c2d1e..5f437864c1 100644 --- a/chromium_src/chrome/browser/printing/printing_message_filter.h +++ b/chromium_src/chrome/browser/printing/printing_message_filter.h @@ -15,6 +15,8 @@ #endif struct PrintHostMsg_ScriptedPrint_Params; +class Profile; +class ProfileIOData; namespace base { class DictionaryValue; @@ -26,18 +28,21 @@ class WebContents; } namespace printing { -class PrinterQuery; + class PrintJobManager; class PrintQueriesQueue; -} +class PrinterQuery; // This class filters out incoming printing related IPC messages for the // renderer process on the IPC thread. class PrintingMessageFilter : public content::BrowserMessageFilter { public: - explicit PrintingMessageFilter(int render_process_id); + PrintingMessageFilter(int render_process_id); // content::BrowserMessageFilter methods. + virtual void OverrideThreadForMessage( + const IPC::Message& message, + content::BrowserThread::ID* thread) OVERRIDE; virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; private: @@ -49,6 +54,25 @@ class PrintingMessageFilter : public content::BrowserMessageFilter { base::SharedMemoryHandle* browser_handle); #endif +#if defined(OS_CHROMEOS) || defined(OS_ANDROID) + // Used to ask the browser allocate a temporary file for the renderer + // to fill in resulting PDF in renderer. + void OnAllocateTempFileForPrinting(int render_view_id, + base::FileDescriptor* temp_file_fd, + int* sequence_number); + void OnTempFileForPrintingWritten(int render_view_id, int sequence_number); +#endif + +#if defined(OS_CHROMEOS) + void CreatePrintDialogForFile(int render_view_id, const base::FilePath& path); +#endif + +#if defined(OS_ANDROID) + // Updates the file descriptor for the PrintViewManagerBasic of a given + // render_view_id. + void UpdateFileDescriptor(int render_view_id, int fd); +#endif + // Given a render_view_id get the corresponding WebContents. // Must be called on the UI thread. content::WebContents* GetWebContentsForRenderView(int render_view_id); @@ -59,38 +83,33 @@ class PrintingMessageFilter : public content::BrowserMessageFilter { // to base::Bind. struct GetPrintSettingsForRenderViewParams; - // Retrieve print settings. Uses |render_view_id| to get a parent - // for any UI created if needed. - void GetPrintSettingsForRenderView( - int render_view_id, - GetPrintSettingsForRenderViewParams params, - const base::Closure& callback, - scoped_refptr printer_query); - - void OnGetPrintSettingsFailed( - const base::Closure& callback, - scoped_refptr printer_query); - // Get the default print setting. void OnGetDefaultPrintSettings(IPC::Message* reply_msg); - void OnGetDefaultPrintSettingsReply( - scoped_refptr printer_query, - IPC::Message* reply_msg); + void OnGetDefaultPrintSettingsReply(scoped_refptr printer_query, + IPC::Message* reply_msg); // The renderer host have to show to the user the print dialog and returns // the selected print settings. The task is handled by the print worker // thread and the UI thread. The reply occurs on the IO thread. void OnScriptedPrint(const PrintHostMsg_ScriptedPrint_Params& params, IPC::Message* reply_msg); - void OnScriptedPrintReply( - scoped_refptr printer_query, - IPC::Message* reply_msg); + void OnScriptedPrintReply(scoped_refptr printer_query, + IPC::Message* reply_msg); + +#if defined(ENABLE_FULL_PRINTING) + // Check to see if print preview has been cancelled. + void OnCheckForCancel(int32 preview_ui_id, + int preview_request_id, + bool* cancel); +#endif const int render_process_id_; - scoped_refptr queue_; + scoped_refptr queue_; DISALLOW_COPY_AND_ASSIGN(PrintingMessageFilter); }; +} // namespace printing + #endif // CHROME_BROWSER_PRINTING_PRINTING_MESSAGE_FILTER_H_ diff --git a/chromium_src/chrome/renderer/printing/print_web_view_helper.cc b/chromium_src/chrome/renderer/printing/print_web_view_helper.cc index df9e287cdc..4e25da8629 100644 --- a/chromium_src/chrome/renderer/printing/print_web_view_helper.cc +++ b/chromium_src/chrome/renderer/printing/print_web_view_helper.cc @@ -22,8 +22,7 @@ #include "content/public/renderer/render_thread.h" #include "content/public/renderer/render_view.h" #include "net/base/escape.h" -#include "printing/metafile.h" -#include "printing/metafile_impl.h" +#include "printing/pdf_metafile_skia.h" #include "printing/units.h" #include "skia/ext/vector_platform_device_skia.h" #include "third_party/WebKit/public/platform/WebSize.h" @@ -65,7 +64,8 @@ bool PrintMsg_Print_Params_IsValid(const PrintMsg_Print_Params& params) { return !params.content_size.IsEmpty() && !params.page_size.IsEmpty() && !params.printable_area.IsEmpty() && params.document_cookie && params.desired_dpi && params.max_shrink && params.min_shrink && - params.dpi && (params.margin_top >= 0) && (params.margin_left >= 0); + params.dpi && (params.margin_top >= 0) && (params.margin_left >= 0) && + params.dpi > kMinDpi && params.document_cookie != 0; } PrintMsg_Print_Params GetCssPrintParams( @@ -409,8 +409,6 @@ class PrepareFrameAndViewForPrint : public blink::WebViewClient, return expected_pages_count_; } - gfx::Size GetPrintCanvasSize() const; - void FinishPrinting(); bool IsLoadingSelection() { @@ -590,12 +588,6 @@ void PrepareFrameAndViewForPrint::CallOnReady() { return on_ready_.Run(); // Can delete |this|. } -gfx::Size PrepareFrameAndViewForPrint::GetPrintCanvasSize() const { - DCHECK(is_printing_started_); - return gfx::Size(web_print_params_.printContentArea.width, - web_print_params_.printContentArea.height); -} - void PrepareFrameAndViewForPrint::RestoreSize() { if (frame()) { blink::WebView* web_view = frame_.GetFrame()->view(); @@ -606,7 +598,7 @@ void PrepareFrameAndViewForPrint::RestoreSize() { } void PrepareFrameAndViewForPrint::FinishPrinting() { - blink::WebFrame* frame = frame_.GetFrame(); + blink::WebLocalFrame* frame = frame_.GetFrame(); if (frame) { blink::WebView* web_view = frame->view(); if (is_printing_started_) { @@ -630,10 +622,15 @@ void PrepareFrameAndViewForPrint::FinishPrinting() { PrintWebViewHelper::PrintWebViewHelper(content::RenderView* render_view) : content::RenderViewObserver(render_view), content::RenderViewObserverTracker(render_view), + reset_prep_frame_view_(false), is_print_ready_metafile_sent_(false), ignore_css_margins_(false), + is_scripted_printing_blocked_(false), notify_browser_of_print_failure_(true), + print_for_preview_(false), print_node_in_progress_(false), + is_loading_(false), + is_scripted_preview_delayed_(false), weak_ptr_factory_(this) { } @@ -673,11 +670,13 @@ bool PrintWebViewHelper::GetPrintFrame(blink::WebLocalFrame** frame) { return true; } +#if !defined(DISABLE_BASIC_PRINTING) void PrintWebViewHelper::OnPrintPages(bool silent, bool print_background) { blink::WebLocalFrame* frame; if (GetPrintFrame(&frame)) Print(frame, blink::WebNode(), silent, print_background); } +#endif // !DISABLE_BASIC_PRINTING void PrintWebViewHelper::GetPageSizeAndContentAreaFromPageLayout( const PageSizeMargins& page_layout_in_points, @@ -726,9 +725,6 @@ void PrintWebViewHelper::PrintNode(const blink::WebNode& node) { } print_node_in_progress_ = true; - - // Make a copy of the node, in case RenderView::OnContextMenuClosed resets - // its |context_menu_node_|. blink::WebNode duplicate_node(node); Print(duplicate_node.document().frame(), duplicate_node); @@ -783,7 +779,7 @@ void PrintWebViewHelper::DidFinishPrinting(PrintingResult result) { break; case FAIL_PRINT: - if (notify_browser_of_print_failure_ && print_pages_params_.get()) { + if (notify_browser_of_print_failure_ && print_pages_params_) { int cookie = print_pages_params_->params.document_cookie; Send(new PrintHostMsg_PrintingFailed(routing_id(), cookie)); } @@ -821,8 +817,7 @@ void PrintWebViewHelper::PrintPages() { page_count)); #endif // !defined(OS_CHROMEOS) - if (!PrintPagesNative(prep_frame_view_->frame(), page_count, - prep_frame_view_->GetPrintCanvasSize())) { + if (!PrintPagesNative(prep_frame_view_->frame(), page_count)) { LOG(ERROR) << "Printing failed."; return DidFinishPrinting(FAIL_PRINT); } @@ -832,10 +827,9 @@ void PrintWebViewHelper::FinishFramePrinting() { prep_frame_view_.reset(); } -#if defined(OS_MACOSX) || defined(OS_WIN) +#if defined(OS_MACOSX) bool PrintWebViewHelper::PrintPagesNative(blink::WebFrame* frame, - int page_count, - const gfx::Size& canvas_size) { + int page_count) { const PrintMsg_PrintPages_Params& params = *print_pages_params_; const PrintMsg_Print_Params& print_params = params.params; @@ -844,20 +838,20 @@ bool PrintWebViewHelper::PrintPagesNative(blink::WebFrame* frame, if (params.pages.empty()) { for (int i = 0; i < page_count; ++i) { page_params.page_number = i; - PrintPageInternal(page_params, canvas_size, frame); + PrintPageInternal(page_params, frame); } } else { for (size_t i = 0; i < params.pages.size(); ++i) { if (params.pages[i] >= page_count) break; page_params.page_number = params.pages[i]; - PrintPageInternal(page_params, canvas_size, frame); + PrintPageInternal(page_params, frame); } } return true; } -#endif // OS_MACOSX || OS_WIN +#endif // OS_MACOSX // static - Not anonymous so that platform implementations can use it. void PrintWebViewHelper::ComputePageLayoutInPointsForCss( @@ -886,13 +880,6 @@ bool PrintWebViewHelper::InitPrintSettings(bool fit_to_paper_size) { if (!PrintMsg_Print_Params_IsValid(settings.params)) result = false; - if (result && - (settings.params.dpi < kMinDpi || settings.params.document_cookie == 0)) { - // Invalid print page settings. - NOTREACHED(); - result = false; - } - // Reset to default values. ignore_css_margins_ = false; settings.pages.clear(); @@ -904,7 +891,7 @@ bool PrintWebViewHelper::InitPrintSettings(bool fit_to_paper_size) { blink::WebPrintScalingOptionFitToPrintableArea; } - print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings)); + SetPrintPagesParams(settings); return result; } @@ -923,8 +910,6 @@ bool PrintWebViewHelper::CalculateNumberOfPages(blink::WebLocalFrame* frame, PrepareFrameAndViewForPrint prepare(params, frame, node, ignore_css_margins_); prepare.StartPrinting(); - Send(new PrintHostMsg_DidGetDocumentCookie(routing_id(), - params.document_cookie)); *number_of_pages = prepare.GetExpectedPageCount(); return true; } @@ -953,9 +938,8 @@ bool PrintWebViewHelper::GetPrintSettingsFromUser(blink::WebFrame* frame, new PrintHostMsg_ScriptedPrint(routing_id(), params, &print_settings); msg->EnableMessagePumping(); Send(msg); - print_pages_params_.reset(new PrintMsg_PrintPages_Params(print_settings)); - - print_pages_params_->params.print_scaling_option = scaling_option; + print_settings.params.print_scaling_option = scaling_option; + SetPrintPagesParams(print_settings); return (print_settings.params.dpi && print_settings.params.document_cookie); } @@ -965,9 +949,8 @@ bool PrintWebViewHelper::RenderPagesForPrint(blink::WebLocalFrame* frame, return false; const PrintMsg_PrintPages_Params& params = *print_pages_params_; const PrintMsg_Print_Params& print_params = params.params; - prep_frame_view_.reset( - new PrepareFrameAndViewForPrint(print_params, frame, node, - ignore_css_margins_)); + prep_frame_view_.reset(new PrepareFrameAndViewForPrint( + print_params, frame, node, ignore_css_margins_)); DCHECK(!print_pages_params_->params.selection_only || print_pages_params_->pages.empty()); prep_frame_view_->CopySelectionIfNeeded( @@ -979,24 +962,27 @@ bool PrintWebViewHelper::RenderPagesForPrint(blink::WebLocalFrame* frame, #if defined(OS_POSIX) bool PrintWebViewHelper::CopyMetafileDataToSharedMem( - Metafile* metafile, + PdfMetafileSkia* metafile, base::SharedMemoryHandle* shared_mem_handle) { uint32 buf_size = metafile->GetDataSize(); scoped_ptr shared_buf( content::RenderThread::Get()->HostAllocateSharedMemoryBuffer( buf_size).release()); - if (shared_buf.get()) { + if (shared_buf) { if (shared_buf->Map(buf_size)) { metafile->GetData(shared_buf->memory(), buf_size); - shared_buf->GiveToProcess(base::GetCurrentProcessHandle(), - shared_mem_handle); - return true; + return shared_buf->GiveToProcess(base::GetCurrentProcessHandle(), + shared_mem_handle); } } - NOTREACHED(); return false; } #endif // defined(OS_POSIX) +void PrintWebViewHelper::SetPrintPagesParams( + const PrintMsg_PrintPages_Params& settings) { + print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings)); +} + } // namespace printing diff --git a/chromium_src/chrome/renderer/printing/print_web_view_helper.h b/chromium_src/chrome/renderer/printing/print_web_view_helper.h index 9ae64be20b..17b8cb05b6 100644 --- a/chromium_src/chrome/renderer/printing/print_web_view_helper.h +++ b/chromium_src/chrome/renderer/printing/print_web_view_helper.h @@ -7,13 +7,15 @@ #include +#include "base/callback.h" +#include "base/gtest_prod_util.h" #include "base/memory/scoped_ptr.h" #include "base/memory/shared_memory.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "content/public/renderer/render_view_observer.h" #include "content/public/renderer/render_view_observer_tracker.h" -#include "printing/metafile_impl.h" +#include "printing/pdf_metafile_skia.h" #include "third_party/WebKit/public/platform/WebCanvas.h" #include "third_party/WebKit/public/web/WebNode.h" #include "third_party/WebKit/public/web/WebPrintParams.h" @@ -22,6 +24,7 @@ struct PrintMsg_Print_Params; struct PrintMsg_PrintPage_Params; struct PrintMsg_PrintPages_Params; +struct PrintHostMsg_SetOptionsFromDocument_Params; namespace base { class DictionaryValue; @@ -81,8 +84,10 @@ class PrintWebViewHelper bool user_initiated) OVERRIDE; // Message handlers --------------------------------------------------------- +#if !defined(DISABLE_BASIC_PRINTING) void OnPrintPages(bool silent, bool print_background); void OnPrintingDone(bool success); +#endif // !DISABLE_BASIC_PRINTING // Get |page_size| and |content_area| information from // |page_layout_in_points|. @@ -125,20 +130,22 @@ class PrintWebViewHelper void OnFramePreparedForPrintPages(); void PrintPages(); - bool PrintPagesNative(blink::WebFrame* frame, - int page_count, - const gfx::Size& canvas_size); + bool PrintPagesNative(blink::WebFrame* frame, int page_count); void FinishFramePrinting(); // Prints the page listed in |params|. #if defined(OS_LINUX) || defined(OS_ANDROID) void PrintPageInternal(const PrintMsg_PrintPage_Params& params, - const gfx::Size& canvas_size, blink::WebFrame* frame, - Metafile* metafile); + PdfMetafileSkia* metafile); +#elif defined(OS_WIN) + void PrintPageInternal(const PrintMsg_PrintPage_Params& params, + blink::WebFrame* frame, + PdfMetafileSkia* metafile, + gfx::Size* page_size_in_dpi, + gfx::Rect* content_area_in_dpi); #else void PrintPageInternal(const PrintMsg_PrintPage_Params& params, - const gfx::Size& canvas_size, blink::WebFrame* frame); #endif @@ -147,24 +154,15 @@ class PrintWebViewHelper const blink::WebNode& node); // Platform specific helper function for rendering page(s) to |metafile|. -#if defined(OS_WIN) +#if defined(OS_MACOSX) void RenderPage(const PrintMsg_Print_Params& params, int page_number, blink::WebFrame* frame, bool is_preview, - Metafile* metafile, - double* scale_factor, - gfx::Size* page_size_in_dpi, - gfx::Rect* content_area_in_dpi); -#elif defined(OS_MACOSX) - void RenderPage(const PrintMsg_Print_Params& params, - int page_number, - blink::WebFrame* frame, - bool is_preview, - Metafile* metafile, + PdfMetafileSkia* metafile, gfx::Size* page_size, gfx::Rect* content_rect); -#endif // defined(OS_WIN) +#endif // defined(OS_MACOSX) // Renders page contents from |frame| to |content_area| of |canvas|. // |page_number| is zero-based. @@ -179,7 +177,7 @@ class PrintWebViewHelper // Helper methods ----------------------------------------------------------- - bool CopyMetafileDataToSharedMem(Metafile* metafile, + bool CopyMetafileDataToSharedMem(PdfMetafileSkia* metafile, base::SharedMemoryHandle* shared_mem_handle); // Helper method to get page layout in points and fit to page if needed. @@ -195,18 +193,35 @@ class PrintWebViewHelper // Script Initiated Printing ------------------------------------------------ + void SetPrintPagesParams(const PrintMsg_PrintPages_Params& settings); + // WebView used only to print the selection. scoped_ptr prep_frame_view_; + bool reset_prep_frame_view_; scoped_ptr print_pages_params_; bool is_print_ready_metafile_sent_; bool ignore_css_margins_; + // Used for scripted initiated printing blocking. + bool is_scripted_printing_blocked_; + // Let the browser process know of a printing failure. Only set to false when // the failure came from the browser in the first place. bool notify_browser_of_print_failure_; + // True, when printing from print preview. + bool print_for_preview_; + bool print_node_in_progress_; + bool is_loading_; + bool is_scripted_preview_delayed_; + + // Used to fix a race condition where the source is a PDF and print preview + // hangs because RequestPrintPreview is called before DidStopLoading() is + // called. This is a store for the RequestPrintPreview() call and its + // parameters so that it can be invoked after DidStopLoading. + base::Closure on_stop_loading_closure_; base::WeakPtrFactory weak_ptr_factory_; diff --git a/chromium_src/chrome/renderer/printing/print_web_view_helper_linux.cc b/chromium_src/chrome/renderer/printing/print_web_view_helper_linux.cc index bf5dfd7039..c42467d45c 100644 --- a/chromium_src/chrome/renderer/printing/print_web_view_helper_linux.cc +++ b/chromium_src/chrome/renderer/printing/print_web_view_helper_linux.cc @@ -8,10 +8,9 @@ #include "base/memory/scoped_ptr.h" #include "chrome/common/print_messages.h" #include "content/public/renderer/render_thread.h" -#include "printing/metafile.h" -#include "printing/metafile_impl.h" #include "printing/metafile_skia_wrapper.h" #include "printing/page_size_margins.h" +#include "printing/pdf_metafile_skia.h" #include "skia/ext/platform_device.h" #include "skia/ext/vector_canvas.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" @@ -27,9 +26,8 @@ namespace printing { using blink::WebFrame; bool PrintWebViewHelper::PrintPagesNative(blink::WebFrame* frame, - int page_count, - const gfx::Size& canvas_size) { - NativeMetafile metafile; + int page_count) { + PdfMetafileSkia metafile; if (!metafile.Init()) return false; @@ -56,7 +54,7 @@ bool PrintWebViewHelper::PrintPagesNative(blink::WebFrame* frame, page_params.params = params.params; for (size_t i = 0; i < printed_pages.size(); ++i) { page_params.page_number = printed_pages[i]; - PrintPageInternal(page_params, canvas_size, frame, &metafile); + PrintPageInternal(page_params, frame, &metafile); } // blink::printEnd() for PDF should be called before metafile is closed. @@ -119,9 +117,8 @@ bool PrintWebViewHelper::PrintPagesNative(blink::WebFrame* frame, void PrintWebViewHelper::PrintPageInternal( const PrintMsg_PrintPage_Params& params, - const gfx::Size& canvas_size, WebFrame* frame, - Metafile* metafile) { + PdfMetafileSkia* metafile) { PageSizeMargins page_layout_in_points; double scale_factor = 1.0f; ComputePageLayoutInPointsForCss(frame, params.page_number, params.params, diff --git a/chromium_src/chrome/renderer/printing/print_web_view_helper_mac.mm b/chromium_src/chrome/renderer/printing/print_web_view_helper_mac.mm index ddd91c88c5..9565269a0b 100644 --- a/chromium_src/chrome/renderer/printing/print_web_view_helper_mac.mm +++ b/chromium_src/chrome/renderer/printing/print_web_view_helper_mac.mm @@ -10,8 +10,6 @@ #include "base/mac/scoped_nsautorelease_pool.h" #include "base/metrics/histogram.h" #include "chrome/common/print_messages.h" -#include "printing/metafile.h" -#include "printing/metafile_impl.h" #include "printing/metafile_skia_wrapper.h" #include "printing/page_size_margins.h" #include "skia/ext/platform_device.h" @@ -25,9 +23,8 @@ using blink::WebFrame; void PrintWebViewHelper::PrintPageInternal( const PrintMsg_PrintPage_Params& params, - const gfx::Size& canvas_size, WebFrame* frame) { - NativeMetafile metafile; + PdfMetafileSkia metafile; if (!metafile.Init()) return; @@ -54,10 +51,13 @@ void PrintWebViewHelper::PrintPageInternal( Send(new PrintHostMsg_DidPrintPage(routing_id(), page_params)); } -void PrintWebViewHelper::RenderPage( - const PrintMsg_Print_Params& params, int page_number, WebFrame* frame, - bool is_preview, Metafile* metafile, gfx::Size* page_size, - gfx::Rect* content_rect) { +void PrintWebViewHelper::RenderPage(const PrintMsg_Print_Params& params, + int page_number, + WebFrame* frame, + bool is_preview, + PdfMetafileSkia* metafile, + gfx::Size* page_size, + gfx::Rect* content_rect) { double scale_factor = 1.0f; double webkit_shrink_factor = frame->getPrintPageShrink(page_number); PageSizeMargins page_layout_in_points; diff --git a/vendor/brightray b/vendor/brightray index 4f04cc8121..f7f439bdd3 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 4f04cc8121dd05ed61a8c94edfa66201e12f0abb +Subproject commit f7f439bdd31c901c802108ec903a3bfc0448c3d1 From 25ea169c72f79f10754dd6998261c912a333803e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 7 Dec 2014 07:43:07 -0800 Subject: [PATCH 02/41] Upgrade libchromiumcontent to 39.0.2171.65 --- script/lib/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/lib/config.py b/script/lib/config.py index 21cc8828b5..01747f7f5a 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -4,7 +4,7 @@ import platform import sys BASE_URL = 'https://gh-contractor-zcbenz.s3.amazonaws.com/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = 'bb95d5c7958c649bb346d59a13ee0d8f15464304' +LIBCHROMIUMCONTENT_COMMIT = 'e4b283c22236560fd289fe59c03e50adf39e7c4b' ARCH = { 'cygwin': '32bit', From 10823eeeaa89f62cf00afd0ee41c3deee1928827 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 7 Dec 2014 07:43:26 -0800 Subject: [PATCH 03/41] Fix compilation errors caused by Chrome 39 --- atom/browser/api/atom_api_content_tracing.cc | 7 +++-- atom/browser/api/atom_api_web_contents.cc | 32 +++++--------------- atom/browser/api/atom_api_web_contents.h | 24 +++++---------- atom/browser/javascript_environment.cc | 3 +- atom/browser/net/adapter_request_job.cc | 14 ++++----- atom/browser/web_view/web_view_manager.cc | 11 +++---- atom/browser/web_view/web_view_manager.h | 12 ++++---- atom/common/api/atom_api_clipboard.cc | 3 +- 8 files changed, 40 insertions(+), 66 deletions(-) diff --git a/atom/browser/api/atom_api_content_tracing.cc b/atom/browser/api/atom_api_content_tracing.cc index 0eff591379..42295fd26c 100644 --- a/atom/browser/api/atom_api_content_tracing.cc +++ b/atom/browser/api/atom_api_content_tracing.cc @@ -69,14 +69,17 @@ void Initialize(v8::Handle exports, v8::Handle unused, dict.SetMethod("startRecording", base::Bind( &TracingController::EnableRecording, base::Unretained(controller))); dict.SetMethod("stopRecording", base::Bind( - &TracingController::DisableRecording, base::Unretained(controller))); + &TracingController::DisableRecording, + base::Unretained(controller), + nullptr)); dict.SetMethod("startMonitoring", base::Bind( &TracingController::EnableMonitoring, base::Unretained(controller))); dict.SetMethod("stopMonitoring", base::Bind( &TracingController::DisableMonitoring, base::Unretained(controller))); dict.SetMethod("captureMonitoringSnapshot", base::Bind( &TracingController::CaptureMonitoringSnapshot, - base::Unretained(controller))); + base::Unretained(controller), + nullptr)); dict.SetMethod("getTraceBufferPercentFull", base::Bind( &TracingController::GetTraceBufferPercentFull, base::Unretained(controller))); diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 9115cbc82a..427a228109 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -225,28 +225,12 @@ void WebContents::WebContentsDestroyed() { Emit("destroyed"); } -void WebContents::WillAttach(content::WebContents* embedder_web_contents, - const base::DictionaryValue& extra_params) { - embedder_web_contents_ = embedder_web_contents; - extra_params_.reset(extra_params.DeepCopy()); -} - -content::WebContents* WebContents::CreateNewGuestWindow( - const content::WebContents::CreateParams& create_params) { - NOTREACHED() << "Should not create new window from guest"; - return nullptr; -} - -void WebContents::DidAttach() { +void WebContents::DidAttach(int guest_proxy_routing_id) { base::ListValue args; args.Append(extra_params_.release()); Emit("did-attach", args); } -int WebContents::GetGuestInstanceID() const { - return guest_instance_id_; -} - void WebContents::ElementSizeChanged(const gfx::Size& old_size, const gfx::Size& new_size) { element_size_ = new_size; @@ -260,18 +244,16 @@ void WebContents::GuestSizeChanged(const gfx::Size& old_size, GuestSizeChangedDueToAutoSize(old_size, new_size); } -void WebContents::RequestPointerLockPermission( - bool user_gesture, - bool last_unlocked_by_target, - const base::Callback& callback) { - callback.Run(true); -} - void WebContents::RegisterDestructionCallback( const DestructionCallback& callback) { destruction_callback_ = callback; } +void WebContents::WillAttach(content::WebContents* embedder_web_contents, + int browser_plugin_instance_id) { + embedder_web_contents_ = embedder_web_contents; +} + void WebContents::Destroy() { if (storage_) { if (!destruction_callback_.is_null()) @@ -294,7 +276,7 @@ void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) { params.referrer = content::Referrer(http_referrer.GetAsReferrer(), blink::WebReferrerPolicyDefault); - params.transition_type = content::PAGE_TRANSITION_TYPED; + params.transition_type = ui::PAGE_TRANSITION_TYPED; params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE; web_contents()->GetController().LoadURLWithParams(params); } diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 7f6a697190..f6442e8a80 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -138,22 +138,14 @@ class WebContents : public mate::EventEmitter, virtual void WebContentsDestroyed() override; // content::BrowserPluginGuestDelegate: - virtual void WillAttach(content::WebContents* embedder_web_contents, - const base::DictionaryValue& extra_params) override; - virtual content::WebContents* CreateNewGuestWindow( - const content::WebContents::CreateParams& create_params) override; - virtual void DidAttach() override; - virtual int GetGuestInstanceID() const override; - virtual void ElementSizeChanged(const gfx::Size& old_size, - const gfx::Size& new_size) override; - virtual void GuestSizeChanged(const gfx::Size& old_size, - const gfx::Size& new_size) override; - virtual void RequestPointerLockPermission( - bool user_gesture, - bool last_unlocked_by_target, - const base::Callback& callback) override; - virtual void RegisterDestructionCallback( - const DestructionCallback& callback) override; + void DidAttach(int guest_proxy_routing_id) final; + void ElementSizeChanged(const gfx::Size& old_size, + const gfx::Size& new_size) final; + void GuestSizeChanged(const gfx::Size& old_size, + const gfx::Size& new_size) final; + void RegisterDestructionCallback(const DestructionCallback& callback) final; + void WillAttach(content::WebContents* embedder_web_contents, + int browser_plugin_instance_id) final; private: // Called when received a message from renderer. diff --git a/atom/browser/javascript_environment.cc b/atom/browser/javascript_environment.cc index e0dd7d54f7..f8dd71f471 100644 --- a/atom/browser/javascript_environment.cc +++ b/atom/browser/javascript_environment.cc @@ -7,8 +7,7 @@ namespace atom { JavascriptEnvironment::JavascriptEnvironment() - : isolate_holder_(gin::IsolateHolder::kNonStrictMode), - isolate_(isolate_holder_.isolate()), + : isolate_(isolate_holder_.isolate()), isolate_scope_(isolate_), locker_(isolate_), handle_scope_(isolate_), diff --git a/atom/browser/net/adapter_request_job.cc b/atom/browser/net/adapter_request_job.cc index eabd65553e..6b5b905aba 100644 --- a/atom/browser/net/adapter_request_job.cc +++ b/atom/browser/net/adapter_request_job.cc @@ -22,7 +22,7 @@ AdapterRequestJob::AdapterRequestJob(ProtocolHandler* protocol_handler, } void AdapterRequestJob::Start() { - DCHECK(!real_job_); + DCHECK(!real_job_.get()); content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, @@ -31,35 +31,35 @@ void AdapterRequestJob::Start() { } void AdapterRequestJob::Kill() { - if (real_job_) // Kill could happen when real_job_ is created. + if (real_job_.get()) // Kill could happen when real_job_ is created. real_job_->Kill(); } bool AdapterRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size, int *bytes_read) { - DCHECK(real_job_); + DCHECK(!real_job_.get()); return real_job_->ReadRawData(buf, buf_size, bytes_read); } bool AdapterRequestJob::IsRedirectResponse(GURL* location, int* http_status_code) { - DCHECK(real_job_); + DCHECK(!real_job_.get()); return real_job_->IsRedirectResponse(location, http_status_code); } net::Filter* AdapterRequestJob::SetupFilter() const { - DCHECK(real_job_); + DCHECK(!real_job_.get()); return real_job_->SetupFilter(); } bool AdapterRequestJob::GetMimeType(std::string* mime_type) const { - DCHECK(real_job_); + DCHECK(!real_job_.get()); return real_job_->GetMimeType(mime_type); } bool AdapterRequestJob::GetCharset(std::string* charset) { - DCHECK(real_job_); + DCHECK(!real_job_.get()); return real_job_->GetCharset(charset); } diff --git a/atom/browser/web_view/web_view_manager.cc b/atom/browser/web_view/web_view_manager.cc index 5dd427c6a7..bc308debad 100644 --- a/atom/browser/web_view/web_view_manager.cc +++ b/atom/browser/web_view/web_view_manager.cc @@ -75,14 +75,13 @@ void WebViewManager::RemoveGuest(int guest_instance_id) { web_contents_map_.erase(guest_instance_id); } -void WebViewManager::MaybeGetGuestByInstanceIDOrKill( - int guest_instance_id, - int embedder_render_process_id, - const GuestByInstanceIDCallback& callback) { +content::WebContents* WebViewManager::GetGuestByInstanceID( + content::WebContents* embedder_web_contents, + int guest_instance_id) { if (ContainsKey(web_contents_map_, guest_instance_id)) - callback.Run(web_contents_map_[guest_instance_id].web_contents); + return web_contents_map_[guest_instance_id].web_contents; else - callback.Run(nullptr); + return nullptr; } bool WebViewManager::ForEachGuest(content::WebContents* embedder_web_contents, diff --git a/atom/browser/web_view/web_view_manager.h b/atom/browser/web_view/web_view_manager.h index e687440895..fb118251e6 100644 --- a/atom/browser/web_view/web_view_manager.h +++ b/atom/browser/web_view/web_view_manager.h @@ -8,6 +8,7 @@ #include #include "content/public/browser/browser_plugin_guest_manager.h" +#include "url/gurl.h" namespace content { class BrowserContext; @@ -30,12 +31,11 @@ class WebViewManager : public content::BrowserPluginGuestManager { protected: // content::BrowserPluginGuestManager: - virtual void MaybeGetGuestByInstanceIDOrKill( - int guest_instance_id, - int embedder_render_process_id, - const GuestByInstanceIDCallback& callback) override; - virtual bool ForEachGuest(content::WebContents* embedder_web_contents, - const GuestCallback& callback) override; + content::WebContents* GetGuestByInstanceID( + content::WebContents* embedder_web_contents, + int browser_plugin_instance_id) override; + bool ForEachGuest(content::WebContents* embedder_web_contents, + const GuestCallback& callback) override; private: struct WebContentsWithEmbedder { diff --git a/atom/common/api/atom_api_clipboard.cc b/atom/common/api/atom_api_clipboard.cc index ee6cc0ccc4..36b8cecb7c 100644 --- a/atom/common/api/atom_api_clipboard.cc +++ b/atom/common/api/atom_api_clipboard.cc @@ -58,8 +58,7 @@ base::string16 ReadText(ui::ClipboardType type) { } void WriteText(const base::string16& text, ui::ClipboardType type) { - ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); - ui::ScopedClipboardWriter writer(clipboard, type); + ui::ScopedClipboardWriter writer(type); writer.WriteText(text); } From 85cf8f91747cfeb969b33065f9c44a024ee49470 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 7 Dec 2014 08:13:42 -0800 Subject: [PATCH 04/41] apm@0.112.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 88d258e125..a0b42404df 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ ], "devDependencies": { - "atom-package-manager": "0.111.0", + "atom-package-manager": "0.112.0", "coffee-script": "~1.7.1", "coffeelint": "~1.3.0" }, From ba347f646018dfcc19156e53a130e7d659df9b5b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 7 Dec 2014 08:51:58 -0800 Subject: [PATCH 05/41] mac: Fix crash reporting on Yosemite --- atom/common/crash_reporter/crash_reporter_mac.mm | 13 +++++++++++++ vendor/breakpad | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/atom/common/crash_reporter/crash_reporter_mac.mm b/atom/common/crash_reporter/crash_reporter_mac.mm index ff1e214dbb..5875bc78f0 100644 --- a/atom/common/crash_reporter/crash_reporter_mac.mm +++ b/atom/common/crash_reporter/crash_reporter_mac.mm @@ -4,6 +4,7 @@ #include "atom/common/crash_reporter/crash_reporter_mac.h" +#include "base/mac/mac_util.h" #include "base/memory/singleton.h" #include "base/strings/sys_string_conversions.h" #import "vendor/breakpad/src/client/apple/Framework/BreakpadDefines.h" @@ -54,7 +55,19 @@ void CrashReporterMac::InitBreakpad(const std::string& product_name, [parameters setValue:base::SysUTF8ToNSString(dump_dir) forKey:@BREAKPAD_DUMP_DIRECTORY]; + // Temporarily run Breakpad in-process on 10.10 and later because APIs that + // it depends on got broken (http://crbug.com/386208). + // This can catch crashes in the browser process only. + if (base::mac::IsOSYosemiteOrLater()) { + [parameters setObject:[NSNumber numberWithBool:YES] + forKey:@BREAKPAD_IN_PROCESS]; + } + breakpad_ = BreakpadCreate(parameters); + if (!breakpad_) { + LOG(ERROR) << "Failed to initialize breakpad"; + return; + } for (StringMap::const_iterator iter = upload_parameters_.begin(); iter != upload_parameters_.end(); ++iter) { diff --git a/vendor/breakpad b/vendor/breakpad index 2483f32da1..b07fb51bdb 160000 --- a/vendor/breakpad +++ b/vendor/breakpad @@ -1 +1 @@ -Subproject commit 2483f32da1f729ac362fbbcaa9173843379697e9 +Subproject commit b07fb51bdb232fee33711e3eb48cb56dd3c257e3 From 5dd73e74cb7a6b0ea86da5f8346f2d61b1f7289c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 7 Dec 2014 08:57:55 -0800 Subject: [PATCH 06/41] Disable crash reporter spec on Yosemite --- spec/api-crash-reporter-spec.coffee | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spec/api-crash-reporter-spec.coffee b/spec/api-crash-reporter-spec.coffee index 43f7b2f035..c9aa025ca3 100644 --- a/spec/api-crash-reporter-spec.coffee +++ b/spec/api-crash-reporter-spec.coffee @@ -8,6 +8,9 @@ formidable = require 'formidable' BrowserWindow = remote.require 'browser-window' describe 'crash-reporter module', -> + # We have trouble makeing crash reporter work on Yosemite. + return if process.platform is 'darwin' + fixtures = path.resolve __dirname, 'fixtures' w = null From 7bc364a3748f88cf86d48cdea7714669bac28516 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 7 Dec 2014 13:09:50 -0800 Subject: [PATCH 07/41] Upgrade node for new V8 API --- atom/browser/api/atom_api_window.cc | 2 -- atom/common/node_bindings.cc | 41 +++++++++++++++++++++++++-- atom/renderer/atom_renderer_client.cc | 2 +- common.gypi | 1 + vendor/node | 2 +- 5 files changed, 41 insertions(+), 7 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 615adb512c..17255fd238 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -72,8 +72,6 @@ Window::Window(const mate::Dictionary& options) Window::~Window() { if (window_) Destroy(); - - Emit("destroyed"); } void Window::OnPageTitleUpdated(bool* prevent_default, diff --git a/atom/common/node_bindings.cc b/atom/common/node_bindings.cc index 9bfd0c4f3c..e43c4d9625 100644 --- a/atom/common/node_bindings.cc +++ b/atom/common/node_bindings.cc @@ -89,6 +89,19 @@ namespace { void UvNoOp(uv_async_t* handle) { } +// Moved from node.cc. +void HandleCloseCb(uv_handle_t* handle) { + node::Environment* env = reinterpret_cast(handle->data); + env->FinishHandleCleanup(handle); +} + +void HandleCleanup(node::Environment* env, + uv_handle_t* handle, + void* arg) { + handle->data = env; + uv_close(handle, HandleCloseCb); +} + // Convert the given vector to an array of C-strings. The strings in the // returned vector are only guaranteed valid so long as the vector of strings // is not modified. @@ -181,6 +194,7 @@ node::Environment* NodeBindings::CreateEnvironment( // Construct the parameters that passed to node::CreateEnvironment: v8::Isolate* isolate = context->GetIsolate(); + uv_loop_t* loop = uv_default_loop(); int argc = args.size(); const char** argv = c_argv.get(); int exec_argc = 0; @@ -191,13 +205,16 @@ node::Environment* NodeBindings::CreateEnvironment( // Following code are stripped from node::CreateEnvironment in node.cc: HandleScope handle_scope(isolate); - Context::Scope context_scope(context); - Environment* env = Environment::New(context); + Context::Scope context_scope(context); + Environment* env = Environment::New(context, loop); + + isolate->SetAutorunMicrotasks(false); uv_check_init(env->event_loop(), env->immediate_check_handle()); uv_unref( reinterpret_cast(env->immediate_check_handle())); + uv_idle_init(env->event_loop(), env->immediate_idle_handle()); uv_prepare_init(env->event_loop(), env->idle_prepare_handle()); @@ -205,6 +222,24 @@ node::Environment* NodeBindings::CreateEnvironment( uv_unref(reinterpret_cast(env->idle_prepare_handle())); uv_unref(reinterpret_cast(env->idle_check_handle())); + // Register handle cleanups + env->RegisterHandleCleanup( + reinterpret_cast(env->immediate_check_handle()), + HandleCleanup, + nullptr); + env->RegisterHandleCleanup( + reinterpret_cast(env->immediate_idle_handle()), + HandleCleanup, + nullptr); + env->RegisterHandleCleanup( + reinterpret_cast(env->idle_prepare_handle()), + HandleCleanup, + nullptr); + env->RegisterHandleCleanup( + reinterpret_cast(env->idle_check_handle()), + HandleCleanup, + nullptr); + Local process_template = FunctionTemplate::New(isolate); process_template->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "process")); @@ -212,7 +247,7 @@ node::Environment* NodeBindings::CreateEnvironment( env->set_process_object(process_object); SetupProcessObject(env, argc, argv, exec_argc, exec_argv); - Load(env); + LoadEnvironment(env); return env; } diff --git a/atom/renderer/atom_renderer_client.cc b/atom/renderer/atom_renderer_client.cc index 7a108d72c5..c910014e19 100644 --- a/atom/renderer/atom_renderer_client.cc +++ b/atom/renderer/atom_renderer_client.cc @@ -92,7 +92,7 @@ void AtomRendererClient::WebKitInitialized() { v8::Isolate* isolate = blink::mainThreadIsolate(); v8::HandleScope handle_scope(isolate); v8::Local context = v8::Context::New(isolate); - global_env = node::Environment::New(context); + global_env = node::Environment::New(context, uv_default_loop()); } void AtomRendererClient::RenderThreadStarted() { diff --git a/common.gypi b/common.gypi index 2bf92e790e..d3835bbd89 100644 --- a/common.gypi +++ b/common.gypi @@ -33,6 +33,7 @@ 'uv_parent_path': 'vendor/node/deps/uv', 'uv_use_dtrace': 'false', 'v8_postmortem_support': 'false', + 'v8_enable_i18n_support': 'false', # Required by Linux (empty for now, should support it in future). 'sysroot': '', }, diff --git a/vendor/node b/vendor/node index 6403ce1c2f..b1d7464f1c 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit 6403ce1c2ff752e81c1145112fa73f9273b8e73a +Subproject commit b1d7464f1c05456027d41fa97384765bc1790212 From a9072049ea34f933057a445c6d0da57b356fe406 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 8 Dec 2014 06:08:21 -0800 Subject: [PATCH 08/41] Move webview code to atom/renderer/lib/web-view --- atom.gyp | 4 ++-- atom/renderer/lib/init.coffee | 2 +- atom/renderer/lib/{ => web-view}/guest-view-internal.coffee | 0 atom/renderer/lib/{ => web-view}/web-view.coffee | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename atom/renderer/lib/{ => web-view}/guest-view-internal.coffee (100%) rename atom/renderer/lib/{ => web-view}/web-view.coffee (100%) diff --git a/atom.gyp b/atom.gyp index 3c368b1b9e..357763e357 100644 --- a/atom.gyp +++ b/atom.gyp @@ -44,11 +44,11 @@ 'atom/common/lib/init.coffee', 'atom/common/lib/asar.coffee', 'atom/renderer/lib/chrome-api.coffee', - 'atom/renderer/lib/guest-view-internal.coffee', 'atom/renderer/lib/init.coffee', 'atom/renderer/lib/inspector.coffee', 'atom/renderer/lib/override.coffee', - 'atom/renderer/lib/web-view.coffee', + 'atom/renderer/lib/web-view/guest-view-internal.coffee', + 'atom/renderer/lib/web-view/web-view.coffee', 'atom/renderer/api/lib/ipc.coffee', 'atom/renderer/api/lib/remote.coffee', 'atom/renderer/api/lib/web-frame.coffee', diff --git a/atom/renderer/lib/init.coffee b/atom/renderer/lib/init.coffee index ebf69ac3a6..13b928573b 100644 --- a/atom/renderer/lib/init.coffee +++ b/atom/renderer/lib/init.coffee @@ -46,7 +46,7 @@ else # Override default web functions. require path.join(__dirname, 'override') # Load webview tag implementation. - require path.join(__dirname, 'web-view') unless process.guestInstanceId? + require path.join(__dirname, 'web-view/web-view') unless process.guestInstanceId? if nodeIntegration in ['true', 'all', 'except-iframe', 'manual-enable-iframe'] # Export node bindings to global. diff --git a/atom/renderer/lib/guest-view-internal.coffee b/atom/renderer/lib/web-view/guest-view-internal.coffee similarity index 100% rename from atom/renderer/lib/guest-view-internal.coffee rename to atom/renderer/lib/web-view/guest-view-internal.coffee diff --git a/atom/renderer/lib/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee similarity index 100% rename from atom/renderer/lib/web-view.coffee rename to atom/renderer/lib/web-view/web-view.coffee From 882a08f61a83238af3b742c8ba892ffc6cd62879 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 8 Dec 2014 08:05:34 -0800 Subject: [PATCH 09/41] Fix browser plugin API changes --- atom.gyp | 1 + atom/browser/api/atom_api_web_contents.cc | 7 ++-- atom/browser/api/atom_api_web_contents.h | 10 +++--- atom/browser/lib/guest-view-manager.coffee | 34 ++++++++++++++++++- atom/renderer/api/atom_api_web_frame.cc | 8 ++++- atom/renderer/api/atom_api_web_frame.h | 1 + .../lib/web-view/guest-view-internal.coffee | 8 ++++- .../lib/web-view/web-view-constants.coffee | 0 atom/renderer/lib/web-view/web-view.coffee | 32 +++++------------ 9 files changed, 66 insertions(+), 35 deletions(-) create mode 100644 atom/renderer/lib/web-view/web-view-constants.coffee diff --git a/atom.gyp b/atom.gyp index 357763e357..283c2c4eec 100644 --- a/atom.gyp +++ b/atom.gyp @@ -49,6 +49,7 @@ 'atom/renderer/lib/override.coffee', 'atom/renderer/lib/web-view/guest-view-internal.coffee', 'atom/renderer/lib/web-view/web-view.coffee', + 'atom/renderer/lib/web-view/web-view-constants.coffee', 'atom/renderer/api/lib/ipc.coffee', 'atom/renderer/api/lib/remote.coffee', 'atom/renderer/api/lib/web-frame.coffee', diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 427a228109..19b6d3276a 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -37,12 +37,14 @@ v8::Persistent template_; WebContents::WebContents(content::WebContents* web_contents) : content::WebContentsObserver(web_contents), guest_instance_id_(-1), + element_instance_id_(-1), guest_opaque_(true), auto_size_enabled_(false) { } WebContents::WebContents(const mate::Dictionary& options) : guest_instance_id_(-1), + element_instance_id_(-1), guest_opaque_(true), auto_size_enabled_(false) { options.Get("guestInstanceId", &guest_instance_id_); @@ -226,9 +228,7 @@ void WebContents::WebContentsDestroyed() { } void WebContents::DidAttach(int guest_proxy_routing_id) { - base::ListValue args; - args.Append(extra_params_.release()); - Emit("did-attach", args); + Emit("did-attach"); } void WebContents::ElementSizeChanged(const gfx::Size& old_size, @@ -252,6 +252,7 @@ void WebContents::RegisterDestructionCallback( void WebContents::WillAttach(content::WebContents* embedder_web_contents, int browser_plugin_instance_id) { embedder_web_contents_ = embedder_web_contents; + element_instance_id_ = browser_plugin_instance_id; } void WebContents::Destroy() { diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index f6442e8a80..8371a65560 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -163,17 +163,15 @@ class WebContents : public mate::EventEmitter, // Unique ID for a guest WebContents. int guest_instance_id_; + // |element_instance_id_| is an identifer that's unique to a particular + // element. + int element_instance_id_; + DestructionCallback destruction_callback_; // Stores whether the contents of the guest can be transparent. bool guest_opaque_; - // The extra parameters associated with this guest view passed - // in from JavaScript. This will typically be the view instance ID, - // the API to use, and view-specific parameters. These parameters - // are passed along to new guests that are created from this guest. - scoped_ptr extra_params_; - // Stores the WebContents that managed by this class. scoped_ptr storage_; diff --git a/atom/browser/lib/guest-view-manager.coffee b/atom/browser/lib/guest-view-manager.coffee index db8ed44848..4f2af53f57 100644 --- a/atom/browser/lib/guest-view-manager.coffee +++ b/atom/browser/lib/guest-view-manager.coffee @@ -18,6 +18,8 @@ supportedWebViewEvents = [ nextInstanceId = 0 guestInstances = {} +embedderElementsMap = {} +reverseEmbedderElementsMap = {} # Generate guestInstanceId. getNextInstanceId = (webContents) -> @@ -41,7 +43,10 @@ createGuest = (embedder, params) -> destroyGuest id if guestInstances[id]? # Init guest web view after attached. - guest.once 'did-attach', (event, params) -> + guest.once 'did-attach', -> + params = @attachParams + delete @attachParams + @viewInstanceId = params.instanceId min = width: params.minwidth, height: params.minheight max = width: params.maxwidth, height: params.maxheight @@ -66,15 +71,42 @@ createGuest = (embedder, params) -> id +# Attach the guest to an element of embedder. +attachGuest = (embedder, elementInstanceId, guestInstanceId, params) -> + guest = guestInstances[guestInstanceId].guest + + # Destroy the old guest when attaching. + key = "#{embedder.getId()}-#{elementInstanceId}" + oldGuestInstanceId = embedderElementsMap[key] + if oldGuestInstanceId? + # Reattachment to the same guest is not currently supported. + return unless oldGuestInstanceId != guestInstanceId + + return unless guestInstances[oldGuestInstanceId]? + destroyGuest oldGuestInstanceId + + guest.attachParams = params + embedderElementsMap[key] = guestInstanceId + reverseEmbedderElementsMap[guestInstanceId] = key + # Destroy an existing guest instance. destroyGuest = (id) -> webViewManager.removeGuest id guestInstances[id].guest.destroy() delete guestInstances[id] + key = reverseEmbedderElementsMap[id] + if key? + delete reverseEmbedderElementsMap[id] + delete embedderElementsMap[key] + ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', (event, type, params, requestId) -> event.sender.send "ATOM_SHELL_RESPONSE_#{requestId}", createGuest(event.sender, params) +ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', (event, elementInstanceId, guestInstanceId, params, requestId) -> + attachGuest event.sender, elementInstanceId, guestInstanceId, params + event.sender.send "ATOM_SHELL_RESPONSE_#{requestId}" + ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', (event, id) -> destroyGuest id diff --git a/atom/renderer/api/atom_api_web_frame.cc b/atom/renderer/api/atom_api_web_frame.cc index 0b80de8e4c..9fc9008ea3 100644 --- a/atom/renderer/api/atom_api_web_frame.cc +++ b/atom/renderer/api/atom_api_web_frame.cc @@ -5,6 +5,7 @@ #include "atom/renderer/api/atom_api_web_frame.h" #include "atom/common/native_mate_converters/string16_converter.h" +#include "content/public/renderer/render_frame.h" #include "native_mate/dictionary.h" #include "native_mate/object_template_builder.h" #include "third_party/WebKit/public/web/WebDocument.h" @@ -51,6 +52,10 @@ v8::Handle WebFrame::RegisterEmbedderCustomElement( return web_frame_->document().registerEmbedderCustomElement(name, options, c); } +void WebFrame::AttachGuest(int id) { + content::RenderFrame::FromWebFrame(web_frame_)->AttachGuest(id); +} + mate::ObjectTemplateBuilder WebFrame::GetObjectTemplateBuilder( v8::Isolate* isolate) { return mate::ObjectTemplateBuilder(isolate) @@ -60,7 +65,8 @@ mate::ObjectTemplateBuilder WebFrame::GetObjectTemplateBuilder( .SetMethod("setZoomFactor", &WebFrame::SetZoomFactor) .SetMethod("getZoomFactor", &WebFrame::GetZoomFactor) .SetMethod("registerEmbedderCustomElement", - &WebFrame::RegisterEmbedderCustomElement); + &WebFrame::RegisterEmbedderCustomElement) + .SetMethod("attachGuest", &WebFrame::AttachGuest); } // static diff --git a/atom/renderer/api/atom_api_web_frame.h b/atom/renderer/api/atom_api_web_frame.h index 955794f229..132199e3fe 100644 --- a/atom/renderer/api/atom_api_web_frame.h +++ b/atom/renderer/api/atom_api_web_frame.h @@ -35,6 +35,7 @@ class WebFrame : public mate::Wrappable { v8::Handle RegisterEmbedderCustomElement( const base::string16& name, v8::Handle options); + void AttachGuest(int element_instance_id); // mate::Wrappable: virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder( diff --git a/atom/renderer/lib/web-view/guest-view-internal.coffee b/atom/renderer/lib/web-view/guest-view-internal.coffee index 76474d27ec..96a8c6edea 100644 --- a/atom/renderer/lib/web-view/guest-view-internal.coffee +++ b/atom/renderer/lib/web-view/guest-view-internal.coffee @@ -1,4 +1,5 @@ ipc = require 'ipc' +webFrame = require 'web-frame' requestId = 0 @@ -36,7 +37,12 @@ module.exports = createGuest: (type, params, callback) -> requestId++ ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', type, params, requestId - ipc.on "ATOM_SHELL_RESPONSE_#{requestId}", callback + ipc.once "ATOM_SHELL_RESPONSE_#{requestId}", callback + + attachGuest: (elementInstanceId, guestInstanceId, params, callback) -> + ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', elementInstanceId, guestInstanceId, params + ipc.once "ATOM_SHELL_RESPONSE_#{requestId}", callback + webFrame.attachGuest elementInstanceId destroyGuest: (guestInstanceId) -> ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', guestInstanceId diff --git a/atom/renderer/lib/web-view/web-view-constants.coffee b/atom/renderer/lib/web-view/web-view-constants.coffee new file mode 100644 index 0000000000..e69de29bb2 diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index 2bae4a9021..d9e8d8e152 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -7,10 +7,6 @@ remote = require 'remote' nextId = 0 getNextId = -> ++nextId -# FIXME -# Discarded after Chrome 39 -PLUGIN_METHOD_ATTACH = '-internal-attach' - # Attributes. WEB_VIEW_ATTRIBUTE_ALLOWTRANSPARENCY = 'allowtransparency' WEB_VIEW_ATTRIBUTE_AUTOSIZE = 'autosize' @@ -103,6 +99,8 @@ class WebView @setupWebviewNodeProperties() @viewInstanceId = getNextId() + + # UPSTREAM: new WebViewEvents(this, this.viewInstanceId); guestViewInternal.registerEvents this, @viewInstanceId shadowRoot.appendChild @browserPluginNode @@ -126,6 +124,7 @@ class WebView # heard back from createGuest yet. We will not reset the flag in this case so # that we don't end up allocating a second guest. if @guestInstanceId + # FIXME guestViewInternal.destroyGuest @guestInstanceId @guestInstanceId = undefined @beforeFirstNavigation = true @@ -295,23 +294,14 @@ class WebView @partition.fromAttribute newValue, @hasNavigated() handleBrowserPluginAttributeMutation: (name, oldValue, newValue) -> - # FIXME - # internalbindings => internalInstanceid after Chrome 39 - if name is 'internalbindings' and !oldValue and !!newValue - @browserPluginNode.removeAttribute 'internalbindings' - # FIXME - # @internalInstanceId = parseInt newValue + if name is 'internalinstanceid' and !oldValue and !!newValue + @browserPluginNode.removeAttribute 'internalinstanceid' + @internalInstanceId = parseInt newValue if !!@guestInstanceId and @guestInstanceId != 0 isNewWindow = if @deferredAttachState then @deferredAttachState.isNewWindow else false params = @buildAttachParams isNewWindow - # FIXME - # guestViewInternalNatives.AttachGuest - # @internalInstanceId, - # @guestInstanceId, - # params, - # (w) => @contentWindow = w - @browserPluginNode[PLUGIN_METHOD_ATTACH] @guestInstanceId, params + guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, params, (w) => @contentWindow = w onSizeChanged: (webViewEvent) -> newWidth = webViewEvent.newWidth @@ -363,9 +353,7 @@ class WebView # Returns if is in the render tree. isPluginInRenderTree: -> - # FIXME - # !!@internalInstanceId && @internalInstanceId != 0 - 'function' == typeof this.browserPluginNode[PLUGIN_METHOD_ATTACH] + !!@internalInstanceId && @internalInstanceId != 0 hasNavigated: -> not @beforeFirstNavigation @@ -480,9 +468,7 @@ class WebView return true @deferredAttachState = null - # FIXME - # guestViewInternalNatives.AttachGuest @internalInstanceId, @guestInstanceId, params, (w) => @contentWindow = w - @browserPluginNode[PLUGIN_METHOD_ATTACH] @guestInstanceId, params + guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, params, (w) => @contentWindow = w # Registers browser plugin custom element. registerBrowserPluginElement = -> From e0f1433c127527ae770e788b4cab52154cc12d1f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 8 Dec 2014 13:36:30 -0800 Subject: [PATCH 10/41] Moved constants out of web-view.coffee and into a new file Imported from: https://chromium.googlesource.com/chromium/src/+/ccbfe27c8d2b4fcb7ddc98064ec6aa5820fcfe9a --- .../lib/web-view/web-view-constants.coffee | 22 ++++ atom/renderer/lib/web-view/web-view.coffee | 100 +++++++----------- 2 files changed, 61 insertions(+), 61 deletions(-) diff --git a/atom/renderer/lib/web-view/web-view-constants.coffee b/atom/renderer/lib/web-view/web-view-constants.coffee index e69de29bb2..37738a8b4b 100644 --- a/atom/renderer/lib/web-view/web-view-constants.coffee +++ b/atom/renderer/lib/web-view/web-view-constants.coffee @@ -0,0 +1,22 @@ +module.exports = + # Attributes. + ATTRIBUTE_ALLOWTRANSPARENCY: 'allowtransparency' + ATTRIBUTE_AUTOSIZE: 'autosize' + ATTRIBUTE_MAXHEIGHT: 'maxheight' + ATTRIBUTE_MAXWIDTH: 'maxwidth' + ATTRIBUTE_MINHEIGHT: 'minheight' + ATTRIBUTE_MINWIDTH: 'minwidth' + ATTRIBUTE_PARTITION: 'partition' + ATTRIBUTE_NODEINTEGRATION: 'nodeintegration' + ATTRIBUTE_PLUGINS: 'plugins' + ATTRIBUTE_PRELOAD: 'preload' + + # Error messages. + ERROR_MSG_ALREADY_NAVIGATED: 'The object has already navigated, so its partition cannot be changed.' + ERROR_MSG_CANNOT_INJECT_SCRIPT: ': ' + + 'Script cannot be injected into content until the page has loaded.' + ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE: ': ' + + 'contentWindow is not available at this time. It will become available ' + + 'when the page has finished loading.' + ERROR_MSG_INVALID_PARTITION_ATTRIBUTE: 'Invalid partition attribute.' + ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE: 'Only "file:" or "asar:" protocol is supported in "preload" attribute.' diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index d9e8d8e152..fef6736590 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -1,43 +1,21 @@ v8Util = process.atomBinding 'v8_util' guestViewInternal = require './guest-view-internal' +webViewConstants = require './web-view-constants' webFrame = require 'web-frame' remote = require 'remote' +AUTO_SIZE_ATTRIBUTES = [ + webViewConstants.ATTRIBUTE_AUTOSIZE, + webViewConstants.ATTRIBUTE_MAXHEIGHT, + webViewConstants.ATTRIBUTE_MAXWIDTH, + webViewConstants.ATTRIBUTE_MINHEIGHT, + webViewConstants.ATTRIBUTE_MINWIDTH, +] + # ID generator. nextId = 0 getNextId = -> ++nextId -# Attributes. -WEB_VIEW_ATTRIBUTE_ALLOWTRANSPARENCY = 'allowtransparency' -WEB_VIEW_ATTRIBUTE_AUTOSIZE = 'autosize' -WEB_VIEW_ATTRIBUTE_MAXHEIGHT = 'maxheight' -WEB_VIEW_ATTRIBUTE_MAXWIDTH = 'maxwidth' -WEB_VIEW_ATTRIBUTE_MINHEIGHT = 'minheight' -WEB_VIEW_ATTRIBUTE_MINWIDTH = 'minwidth' -WEB_VIEW_ATTRIBUTE_PARTITION = 'partition' -WEB_VIEW_ATTRIBUTE_NODEINTEGRATION = 'nodeintegration' -WEB_VIEW_ATTRIBUTE_PLUGINS = 'plugins' -WEB_VIEW_ATTRIBUTE_PRELOAD = 'preload' -AUTO_SIZE_ATTRIBUTES = [ - WEB_VIEW_ATTRIBUTE_AUTOSIZE, - WEB_VIEW_ATTRIBUTE_MAXHEIGHT, - WEB_VIEW_ATTRIBUTE_MAXWIDTH, - WEB_VIEW_ATTRIBUTE_MINHEIGHT, - WEB_VIEW_ATTRIBUTE_MINWIDTH, -] - -# Error messages. -ERROR_MSG_ALREADY_NAVIGATED = - 'The object has already navigated, so its partition cannot be changed.' -ERROR_MSG_CANNOT_INJECT_SCRIPT = ': ' + - 'Script cannot be injected into content until the page has loaded.' -ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE = ': ' + - 'contentWindow is not available at this time. It will become available ' + - 'when the page has finished loading.' -ERROR_MSG_INVALID_PARTITION_ATTRIBUTE = 'Invalid partition attribute.' -ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE = - 'Only "file:" or "asar:" protocol is supported in "preload" attribute.' - # Represents the state of the storage partition. class Partition constructor: -> @@ -52,7 +30,7 @@ class Partition fromAttribute: (value, hasNavigated) -> result = {} if hasNavigated - result.error = ERROR_MSG_ALREADY_NAVIGATED + result.error = webViewConstants.ERROR_MSG_ALREADY_NAVIGATED return result value ?= '' @@ -61,7 +39,7 @@ class Partition value = value.substr LEN unless value @validPartitionId = false - result.error = ERROR_MSG_INVALID_PARTITION_ATTRIBUTE + result.error = webViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE return result @persistStorage = true else @@ -153,7 +131,7 @@ class WebView # Validation helper function for executeScript() and insertCSS(). validateExecuteCodeCall: -> - throw new Error(ERROR_MSG_CANNOT_INJECT_SCRIPT) unless @guestInstanceId + throw new Error(webViewConstants.ERROR_MSG_CANNOT_INJECT_SCRIPT) unless @guestInstanceId setupAutoSizeProperties: -> for attributeName in AUTO_SIZE_ATTRIBUTES @@ -166,10 +144,10 @@ class WebView setupWebviewNodeProperties: -> @setupAutoSizeProperties() - Object.defineProperty @webviewNode, WEB_VIEW_ATTRIBUTE_ALLOWTRANSPARENCY, + Object.defineProperty @webviewNode, webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY, get: => @allowtransparency set: (value) => - @webviewNode.setAttribute WEB_VIEW_ATTRIBUTE_ALLOWTRANSPARENCY, value + @webviewNode.setAttribute webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY, value enumerable: true # We cannot use {writable: true} property descriptor because we want a @@ -177,7 +155,7 @@ class WebView Object.defineProperty @webviewNode, 'contentWindow', get: => return @contentWindow if @contentWindow? - window.console.error ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE + window.console.error webViewConstants.ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE # No setter. enumerable: true @@ -229,7 +207,7 @@ class WebView this[name] = newValue return unless @guestInstanceId # Convert autosize attribute to boolean. - autosize = @webviewNode.hasAttribute WEB_VIEW_ATTRIBUTE_AUTOSIZE + autosize = @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_AUTOSIZE guestViewInternal.setAutoSize @guestInstanceId, enableAutoSize: autosize, min: @@ -238,7 +216,7 @@ class WebView max: width: parseInt @maxwidth || 0 height: parseInt @maxheight || 0 - else if name is WEB_VIEW_ATTRIBUTE_ALLOWTRANSPARENCY + else if name is webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY # We treat null attribute (attribute removed) and the empty string as # one case. oldValue ?= '' @@ -314,33 +292,33 @@ class WebView # Check the current bounds to make sure we do not resize # outside of current constraints. - if node.hasAttribute(WEB_VIEW_ATTRIBUTE_MAXWIDTH) and - node[WEB_VIEW_ATTRIBUTE_MAXWIDTH] - maxWidth = node[WEB_VIEW_ATTRIBUTE_MAXWIDTH] + if node.hasAttribute(webViewConstants.ATTRIBUTE_MAXWIDTH) and + node[webViewConstants.ATTRIBUTE_MAXWIDTH] + maxWidth = node[webViewConstants.ATTRIBUTE_MAXWIDTH] else maxWidth = width - if node.hasAttribute(WEB_VIEW_ATTRIBUTE_MINWIDTH) and - node[WEB_VIEW_ATTRIBUTE_MINWIDTH] - minWidth = node[WEB_VIEW_ATTRIBUTE_MINWIDTH] + if node.hasAttribute(webViewConstants.ATTRIBUTE_MINWIDTH) and + node[webViewConstants.ATTRIBUTE_MINWIDTH] + minWidth = node[webViewConstants.ATTRIBUTE_MINWIDTH] else minWidth = width minWidth = maxWidth if minWidth > maxWidth - if node.hasAttribute(WEB_VIEW_ATTRIBUTE_MAXHEIGHT) and - node[WEB_VIEW_ATTRIBUTE_MAXHEIGHT] - maxHeight = node[WEB_VIEW_ATTRIBUTE_MAXHEIGHT] + if node.hasAttribute(webViewConstants.ATTRIBUTE_MAXHEIGHT) and + node[webViewConstants.ATTRIBUTE_MAXHEIGHT] + maxHeight = node[webViewConstants.ATTRIBUTE_MAXHEIGHT] else maxHeight = height - if node.hasAttribute(WEB_VIEW_ATTRIBUTE_MINHEIGHT) and - node[WEB_VIEW_ATTRIBUTE_MINHEIGHT] - minHeight = node[WEB_VIEW_ATTRIBUTE_MINHEIGHT] + if node.hasAttribute(webViewConstants.ATTRIBUTE_MINHEIGHT) and + node[webViewConstants.ATTRIBUTE_MINHEIGHT] + minHeight = node[webViewConstants.ATTRIBUTE_MINHEIGHT] else minHeight = height minHeight = maxHeight if minHeight > maxHeight - if not @webviewNode.hasAttribute WEB_VIEW_ATTRIBUTE_AUTOSIZE or + if not @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_AUTOSIZE or (newWidth >= minWidth and newWidth <= maxWidth and newHeight >= minHeight and @@ -360,7 +338,7 @@ class WebView parseSrcAttribute: (result) -> unless @partition.validPartitionId - result.error = ERROR_MSG_INVALID_PARTITION_ATTRIBUTE + result.error = webViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE return @src = @webviewNode.getAttribute 'src' @@ -386,14 +364,14 @@ class WebView createGuest: -> return if @pendingGuestCreation storagePartitionId = - @webviewNode.getAttribute(WEB_VIEW_ATTRIBUTE_PARTITION) or - @webviewNode[WEB_VIEW_ATTRIBUTE_PARTITION] + @webviewNode.getAttribute(webViewConstants.ATTRIBUTE_PARTITION) or + @webviewNode[webViewConstants.ATTRIBUTE_PARTITION] params = storagePartitionId: storagePartitionId - nodeIntegration: @webviewNode.hasAttribute WEB_VIEW_ATTRIBUTE_NODEINTEGRATION - plugins: @webviewNode.hasAttribute WEB_VIEW_ATTRIBUTE_PLUGINS - if @webviewNode.hasAttribute WEB_VIEW_ATTRIBUTE_PRELOAD - preload = @webviewNode.getAttribute WEB_VIEW_ATTRIBUTE_PRELOAD + nodeIntegration: @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_NODEINTEGRATION + plugins: @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_PLUGINS + if @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_PRELOAD + preload = @webviewNode.getAttribute webViewConstants.ATTRIBUTE_PRELOAD # Get the full path. a = document.createElement 'a' a.href = preload @@ -402,7 +380,7 @@ class WebView protocol = params.preload.substr 0, 5 unless protocol in ['file:', 'asar:'] delete params.preload - console.error ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE + console.error webViewConstants.ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE guestViewInternal.createGuest 'webview', params, (guestInstanceId) => @pendingGuestCreation = false unless @elementAttached @@ -445,7 +423,7 @@ class WebView buildAttachParams: (isNewWindow) -> allowtransparency: @allowtransparency || false - autosize: @webviewNode.hasAttribute WEB_VIEW_ATTRIBUTE_AUTOSIZE + autosize: @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_AUTOSIZE instanceId: @viewInstanceId maxheight: parseInt @maxheight || 0 maxwidth: parseInt @maxwidth || 0 From d7eae695877196497f8915752e31394748325fb8 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 8 Dec 2014 16:14:12 -0800 Subject: [PATCH 11/41] Webview attributes overhaul Imported from: https://chromium.googlesource.com/chromium/src/+/884a5b43cba6a19b8d067fed99dc2906ed0ef656 --- atom.gyp | 1 + atom/renderer/lib/init.coffee | 10 +- .../lib/web-view/web-view-attributes.coffee | 71 +++++++++ .../lib/web-view/web-view-constants.coffee | 6 + atom/renderer/lib/web-view/web-view.coffee | 148 ++++++++---------- 5 files changed, 145 insertions(+), 91 deletions(-) create mode 100644 atom/renderer/lib/web-view/web-view-attributes.coffee diff --git a/atom.gyp b/atom.gyp index 283c2c4eec..0e651b1aa2 100644 --- a/atom.gyp +++ b/atom.gyp @@ -49,6 +49,7 @@ 'atom/renderer/lib/override.coffee', 'atom/renderer/lib/web-view/guest-view-internal.coffee', 'atom/renderer/lib/web-view/web-view.coffee', + 'atom/renderer/lib/web-view/web-view-attributes.coffee', 'atom/renderer/lib/web-view/web-view-constants.coffee', 'atom/renderer/api/lib/ipc.coffee', 'atom/renderer/api/lib/remote.coffee', diff --git a/atom/renderer/lib/init.coffee b/atom/renderer/lib/init.coffee index 13b928573b..c2ca2feb32 100644 --- a/atom/renderer/lib/init.coffee +++ b/atom/renderer/lib/init.coffee @@ -36,17 +36,19 @@ for arg in process.argv if location.protocol is 'chrome-devtools:' # Override some inspector APIs. - require path.join(__dirname, 'inspector') + require './inspector' nodeIntegration = 'true' else if location.protocol is 'chrome-extension:' # Add implementations of chrome API. - require path.join(__dirname, 'chrome-api') + require './chrome-api' nodeIntegration = 'true' else # Override default web functions. - require path.join(__dirname, 'override') + require './override' # Load webview tag implementation. - require path.join(__dirname, 'web-view/web-view') unless process.guestInstanceId? + unless process.guestInstanceId? + require './web-view/web-view' + require './web-view/web-view-attributes' if nodeIntegration in ['true', 'all', 'except-iframe', 'manual-enable-iframe'] # Export node bindings to global. diff --git a/atom/renderer/lib/web-view/web-view-attributes.coffee b/atom/renderer/lib/web-view/web-view-attributes.coffee new file mode 100644 index 0000000000..5279ed3a91 --- /dev/null +++ b/atom/renderer/lib/web-view/web-view-attributes.coffee @@ -0,0 +1,71 @@ +WebView = require './web-view' +webViewConstants = require './web-view-constants' + +# Attribute objects. +# Default implementation of a WebView attribute. +class WebViewAttribute + constructor: (name, webViewImpl) -> + @name = name + @value = '' + @webViewImpl = webViewImpl + + getValue: -> @value || '' + + setValue: (value) -> @value = value + +# Attribute representing the state of the storage partition. +class Partition extends WebViewAttribute + constructor: (webViewImpl) -> + super webViewConstants.ATTRIBUTE_PARTITION, webViewImpl + + @validPartitionId = true + @persistStorage = false + @storagePartitionId = '' + @webViewImpl = webViewImpl + + getValue: -> + return '' unless @validPartitionId + (if @persistStorage then 'persist:' else '') + @storagePartitionId + + setValue: (value) -> + result = {} + hasNavigated = !@webViewImpl.beforeFirstNavigation + if hasNavigated + result.error = webViewConstants.ERROR_MSG_ALREADY_NAVIGATED + return result + value = '' unless value + LEN = 'persist:'.length + if value.substr(0, LEN) == 'persist:' + value = value.substr LEN + unless value + @validPartitionId = false + result.error = webViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE + return result + @persistStorage = true + else + @persistStorage = false + @storagePartitionId = value + result + +# Sets up all of the webview attributes. +WebView::setupWebViewAttributes = -> + @attributes = {} + + # Initialize the attributes with special behavior (and custom attribute + # objects). + @attributes[webViewConstants.ATTRIBUTE_PARTITION] = new Partition(this) + + # Initialize the remaining attributes, which have default behavior. + defaultAttributes = [ + webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY + webViewConstants.ATTRIBUTE_AUTOSIZE + webViewConstants.ATTRIBUTE_MAXHEIGHT + webViewConstants.ATTRIBUTE_MAXWIDTH + webViewConstants.ATTRIBUTE_MINHEIGHT + webViewConstants.ATTRIBUTE_MINWIDTH + webViewConstants.ATTRIBUTE_SRC + webViewConstants.ATTRIBUTE_HTTPREFERRER + ] + + for attribute in defaultAttributes + @attributes[attribute] = new WebViewAttribute(attribute, this) diff --git a/atom/renderer/lib/web-view/web-view-constants.coffee b/atom/renderer/lib/web-view/web-view-constants.coffee index 37738a8b4b..f40f14c4d7 100644 --- a/atom/renderer/lib/web-view/web-view-constants.coffee +++ b/atom/renderer/lib/web-view/web-view-constants.coffee @@ -6,11 +6,17 @@ module.exports = ATTRIBUTE_MAXWIDTH: 'maxwidth' ATTRIBUTE_MINHEIGHT: 'minheight' ATTRIBUTE_MINWIDTH: 'minwidth' + ATTRIBUTE_NAME: 'name' ATTRIBUTE_PARTITION: 'partition' + ATTRIBUTE_SRC: 'src' + ATTRIBUTE_HTTPREFERRER: 'httpreferrer' ATTRIBUTE_NODEINTEGRATION: 'nodeintegration' ATTRIBUTE_PLUGINS: 'plugins' ATTRIBUTE_PRELOAD: 'preload' + # Internal attribute. + ATTRIBUTE_INTERNALINSTANCEID: 'internalinstanceid' + # Error messages. ERROR_MSG_ALREADY_NAVIGATED: 'The object has already navigated, so its partition cannot be changed.' ERROR_MSG_CANNOT_INJECT_SCRIPT: ': ' + diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index fef6736590..99f555f431 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -4,6 +4,7 @@ webViewConstants = require './web-view-constants' webFrame = require 'web-frame' remote = require 'remote' +# Attributes. AUTO_SIZE_ATTRIBUTES = [ webViewConstants.ATTRIBUTE_AUTOSIZE, webViewConstants.ATTRIBUTE_MAXHEIGHT, @@ -16,38 +17,6 @@ AUTO_SIZE_ATTRIBUTES = [ nextId = 0 getNextId = -> ++nextId -# Represents the state of the storage partition. -class Partition - constructor: -> - @validPartitionId = true - @persistStorage = false - @storagePartitionId = '' - - toAttribute: -> - return '' unless @validPartitionId - (if @persistStorage then 'persist:' else '') + @storagePartitionId - - fromAttribute: (value, hasNavigated) -> - result = {} - if hasNavigated - result.error = webViewConstants.ERROR_MSG_ALREADY_NAVIGATED - return result - value ?= '' - - LEN = 'persist:'.length - if value.substr(0, LEN) == 'persist:' - value = value.substr LEN - unless value - @validPartitionId = false - result.error = webViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE - return result - @persistStorage = true - else - @persistStorage = false - - @storagePartitionId = value - result - # Represents the internal state of the WebView node. class WebView constructor: (@webviewNode) -> @@ -70,8 +39,7 @@ class WebView @browserPluginNode = @createBrowserPluginNode() shadowRoot = @webviewNode.createShadowRoot() - @partition = new Partition() - + @setupWebViewAttributes() @setupWebViewSrcAttributeMutationObserver() @setupFocusPropagation() @setupWebviewNodeProperties() @@ -107,7 +75,7 @@ class WebView @guestInstanceId = undefined @beforeFirstNavigation = true @validPartitionId = true - @partition.validPartitionId = true + @attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId = true @contentWindow = null @internalInstanceId = 0 @@ -135,9 +103,9 @@ class WebView setupAutoSizeProperties: -> for attributeName in AUTO_SIZE_ATTRIBUTES - this[attributeName] = @webviewNode.getAttribute attributeName + @attributes[attributeName].setValue @webviewNode.getAttribute(attributeName) Object.defineProperty @webviewNode, attributeName, - get: => this[attributeName] + get: => @attributes[attributeName].getValue() set: (value) => @webviewNode.setAttribute attributeName, value enumerable: true @@ -145,7 +113,7 @@ class WebView @setupAutoSizeProperties() Object.defineProperty @webviewNode, webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY, - get: => @allowtransparency + get: => @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].getValue() set: (value) => @webviewNode.setAttribute webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY, value enumerable: true @@ -159,25 +127,24 @@ class WebView # No setter. enumerable: true - Object.defineProperty @webviewNode, 'partition', - get: => @partition.toAttribute() + Object.defineProperty @webviewNode, webViewConstants.ATTRIBUTE_PARTITION, + get: => @attributes[webViewConstants.ATTRIBUTE_PARTITION].getValue() set: (value) => - result = @partition.fromAttribute value, @hasNavigated() + result = @attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue value throw result.error if result.error? - @webviewNode.setAttribute 'partition', value + @webviewNode.setAttribute webViewConstants.ATTRIBUTE_PARTITION, value enumerable: true - @src = @webviewNode.getAttribute 'src' - Object.defineProperty @webviewNode, 'src', - get: => @src - set: (value) => @webviewNode.setAttribute 'src', value - # No setter. + @attributes[webViewConstants.ATTRIBUTE_SRC].setValue @webviewNode.getAttribute(webViewConstants.ATTRIBUTE_SRC) + Object.defineProperty @webviewNode, webViewConstants.ATTRIBUTE_SRC, + get: => @attributes[webViewConstants.ATTRIBUTE_SRC].getValue() + set: (value) => @webviewNode.setAttribute webViewConstants.ATTRIBUTE_SRC, value enumerable: true - @httpreferrer = @webviewNode.getAttribute 'httpreferrer' - Object.defineProperty @webviewNode, 'httpreferrer', - get: => @httpreferrer - set: (value) => @webviewNode.setAttribute 'httpreferrer', value + @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].setValue @webviewNode.getAttribute(webViewConstants.ATTRIBUTE_HTTPREFERRER) + Object.defineProperty @webviewNode, webViewConstants.ATTRIBUTE_HTTPREFERRER, + get: => @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].getValue() + set: (value) => @webviewNode.setAttribute webViewConstants.ATTRIBUTE_HTTPREFERRER, value enumerable: true # The purpose of this mutation observer is to catch assignment to the src @@ -194,7 +161,11 @@ class WebView params = attributes: true, attributeOldValue: true, - attributeFilter: ['src', 'partition', 'httpreferrer'] + attributeFilter: [ + webViewConstants.ATTRIBUTE_SRC + webViewConstants.ATTRIBUTE_PARTITION + webViewConstants.ATTRIBUTE_HTTPREFERRER + ] @srcAndPartitionObserver.observe @webviewNode, params # This observer monitors mutations to attributes of the and @@ -204,18 +175,18 @@ class WebView # details. handleWebviewAttributeMutation: (name, oldValue, newValue) -> if name in AUTO_SIZE_ATTRIBUTES - this[name] = newValue + @attributes[name].setValue newValue return unless @guestInstanceId # Convert autosize attribute to boolean. autosize = @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_AUTOSIZE guestViewInternal.setAutoSize @guestInstanceId, enableAutoSize: autosize, min: - width: parseInt @minwidth || 0 - height: parseInt @minheight || 0 + width: parseInt @attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() || 0 + height: parseInt @attributes[webViewConstants.ATTRIBUTE_MINHEIGHT].getValue() || 0 max: - width: parseInt @maxwidth || 0 - height: parseInt @maxheight || 0 + width: parseInt @attributes[webViewConstants.ATTRIBUTE_MAXWIDTH].getValue() || 0 + height: parseInt @attributes[webViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() || 0 else if name is webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY # We treat null attribute (attribute removed) and the empty string as # one case. @@ -223,19 +194,19 @@ class WebView newValue ?= '' return if oldValue is newValue - @allowtransparency = newValue != '' + @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].setValue(newValue != '') return unless @guestInstanceId - guestViewInternal.setAllowTransparency @guestInstanceId, @allowtransparency - else if name is 'httpreferrer' + guestViewInternal.setAllowTransparency @guestInstanceId, @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].getValue() + else if name is webViewConstants.ATTRIBUTE_HTTPREFERRER oldValue ?= '' newValue ?= '' if newValue == '' and oldValue != '' - @webviewNode.setAttribute 'httpreferrer', oldValue + @webviewNode.setAttribute webViewConstants.ATTRIBUTE_HTTPREFERRER, oldValue - @httpreferrer = newValue + @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].setValue newValue result = {} # If the httpreferrer changes treat it as though the src changes and reload @@ -243,7 +214,7 @@ class WebView @parseSrcAttribute result throw result.error if result.error? - else if name is 'src' + else if name is webViewConstants.ATTRIBUTE_SRC # We treat null attribute (attribute removed) and the empty string as # one case. oldValue ?= '' @@ -256,7 +227,7 @@ class WebView # the next src attribute handler call to avoid reloading the page # on every guest-initiated navigation. @ignoreNextSrcAttributeChange = true - @webviewNode.setAttribute 'src', oldValue + @webviewNode.setAttribute webViewConstants.ATTRIBUTE_SRC, oldValue @src = newValue if @ignoreNextSrcAttributeChange # Don't allow the src mutation observer to see this change. @@ -267,13 +238,13 @@ class WebView @parseSrcAttribute result throw result.error if result.error? - else if name is 'partition' + else if name is webViewConstants.ATTRIBUTE_PARTITION # Note that throwing error here won't synchronously propagate. - @partition.fromAttribute newValue, @hasNavigated() + @attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue newValue handleBrowserPluginAttributeMutation: (name, oldValue, newValue) -> - if name is 'internalinstanceid' and !oldValue and !!newValue - @browserPluginNode.removeAttribute 'internalinstanceid' + if name is webViewConstants.ATTRIBUTE_INTERNALINSTANCEID and !oldValue and !!newValue + @browserPluginNode.removeAttribute webViewConstants.ATTRIBUTE_INTERNALINSTANCEID @internalInstanceId = parseInt newValue if !!@guestInstanceId and @guestInstanceId != 0 @@ -337,12 +308,12 @@ class WebView not @beforeFirstNavigation parseSrcAttribute: (result) -> - unless @partition.validPartitionId + unless @attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId result.error = webViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE return - @src = @webviewNode.getAttribute 'src' + @attributes[webViewConstants.ATTRIBUTE_SRC].setValue @webviewNode.getAttribute(webViewConstants.ATTRIBUTE_SRC) - return unless @src + return unless @attributes[webViewConstants.ATTRIBUTE_SRC].getValue() unless @guestInstanceId? if @beforeFirstNavigation @@ -351,14 +322,15 @@ class WebView return # Navigate to |this.src|. - urlOptions = if @httpreferrer then {@httpreferrer} else {} - remote.getGuestWebContents(@guestInstanceId).loadUrl @src, urlOptions + httpreferrer = @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].getValue() + urlOptions = if httpreferrer then {httpreferrer} else {} + remote.getGuestWebContents(@guestInstanceId).loadUrl @attributes[webViewConstants.ATTRIBUTE_SRC].getValue(), urlOptions parseAttributes: -> return unless @elementAttached hasNavigated = @hasNavigated() - attributeValue = @webviewNode.getAttribute 'partition' - result = @partition.fromAttribute attributeValue, hasNavigated + attributeValue = @webviewNode.getAttribute webViewConstants.ATTRIBUTE_PARTITION + result = @attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue attributeValue @parseSrcAttribute result createGuest: -> @@ -408,34 +380,34 @@ class WebView # Updates state upon loadcommit. onLoadCommit: (@baseUrlForDataUrl, @currentEntryIndex, @entryCount, @processId, url, isTopLevel) -> - oldValue = @webviewNode.getAttribute 'src' + oldValue = @webviewNode.getAttribute webViewConstants.ATTRIBUTE_SRC newValue = url if isTopLevel and (oldValue != newValue) # Touching the src attribute triggers a navigation. To avoid # triggering a page reload on every guest-initiated navigation, # we use the flag ignoreNextSrcAttributeChange here. this.ignoreNextSrcAttributeChange = true - this.webviewNode.setAttribute 'src', newValue + this.webviewNode.setAttribute webViewConstants.ATTRIBUTE_SRC, newValue onAttach: (storagePartitionId) -> - @webviewNode.setAttribute 'partition', storagePartitionId - @partition.fromAttribute storagePartitionId, this.hasNavigated() + @webviewNode.setAttribute webViewConstants.ATTRIBUTE_PARTITION, storagePartitionId + @attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue storagePartitionId buildAttachParams: (isNewWindow) -> - allowtransparency: @allowtransparency || false + allowtransparency: @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].getValue() || false autosize: @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_AUTOSIZE instanceId: @viewInstanceId - maxheight: parseInt @maxheight || 0 - maxwidth: parseInt @maxwidth || 0 - minheight: parseInt @minheight || 0 - minwidth: parseInt @minwidth || 0 + maxheight: parseInt @attributes[webViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() || 0 + maxwidth: parseInt @attributes[webViewConstants.ATTRIBUTE_MAXWIDTH].getValue() || 0 + minheight: parseInt @attributes[webViewConstants.ATTRIBUTE_MINHEIGHT].getValue() || 0 + minwidth: parseInt @attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() || 0 # We don't need to navigate new window from here. - src: if isNewWindow then undefined else @src + src: if isNewWindow then undefined else @attributes[webViewConstants.ATTRIBUTE_SRC].getValue() # If we have a partition from the opener, that will also be already # set via this.onAttach(). - storagePartitionId: @partition.toAttribute() + storagePartitionId: @attributes[webViewConstants.ATTRIBUTE_PARTITION].getValue() userAgentOverride: @userAgentOverride - httpreferrer: @httpreferrer + httpreferrer: @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].getValue() attachWindow: (guestInstanceId, isNewWindow) -> @guestInstanceId = guestInstanceId @@ -552,3 +524,5 @@ listener = (event) -> registerWebViewElement() window.removeEventListener event.type, listener, useCapture window.addEventListener 'readystatechange', listener, true + +module.exports = WebView From 2c27b953b57413201332c46a972e508d8191c16b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 8 Dec 2014 16:56:14 -0800 Subject: [PATCH 12/41] Got rid of the internal copies of webview attributes Imported from: https://chromium.googlesource.com/chromium/src/+/abb035a09b79c2e0b6d9fb87b47e823e2f8e0549%5E%21/ --- .../lib/web-view/web-view-attributes.coffee | 70 ++++++++------ atom/renderer/lib/web-view/web-view.coffee | 96 +++++++------------ 2 files changed, 75 insertions(+), 91 deletions(-) diff --git a/atom/renderer/lib/web-view/web-view-attributes.coffee b/atom/renderer/lib/web-view/web-view-attributes.coffee index 5279ed3a91..3d96859bb5 100644 --- a/atom/renderer/lib/web-view/web-view-attributes.coffee +++ b/atom/renderer/lib/web-view/web-view-attributes.coffee @@ -6,46 +6,52 @@ webViewConstants = require './web-view-constants' class WebViewAttribute constructor: (name, webViewImpl) -> @name = name - @value = '' @webViewImpl = webViewImpl + @ignoreNextMutation = false - getValue: -> @value || '' + # Retrieves and returns the attribute's value. + getValue: -> @webViewImpl.webviewNode.getAttribute(@name) || '' - setValue: (value) -> @value = value + # Sets the attribute's value. + setValue: (value) -> @webViewImpl.webviewNode.setAttribute(@name, value || '') + + # Called when the attribute's value changes. + handleMutation: -> + +# Attribute specifying whether transparency is allowed in the webview. +class BooleanAttribute extends WebViewAttribute + constructor: (name, webViewImpl) -> + super name, webViewImpl + + getValue: -> + # This attribute is treated as a boolean, and is retrieved as such. + @webViewImpl.webviewNode.hasAttribute @name + + setValue: (value) -> + unless value + @webViewImpl.webviewNode.removeAttribute @name + else + @webViewImpl.webviewNode.setAttribute @name, '' # Attribute representing the state of the storage partition. class Partition extends WebViewAttribute constructor: (webViewImpl) -> super webViewConstants.ATTRIBUTE_PARTITION, webViewImpl - @validPartitionId = true - @persistStorage = false - @storagePartitionId = '' - @webViewImpl = webViewImpl - getValue: -> - return '' unless @validPartitionId - (if @persistStorage then 'persist:' else '') + @storagePartitionId + handleMutation: (oldValue, newValue) -> + newValue = newValue || '' - setValue: (value) -> - result = {} - hasNavigated = !@webViewImpl.beforeFirstNavigation - if hasNavigated - result.error = webViewConstants.ERROR_MSG_ALREADY_NAVIGATED - return result - value = '' unless value - LEN = 'persist:'.length - if value.substr(0, LEN) == 'persist:' - value = value.substr LEN - unless value - @validPartitionId = false - result.error = webViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE - return result - @persistStorage = true - else - @persistStorage = false - @storagePartitionId = value - result + # The partition cannot change if the webview has already navigated. + unless @webViewImpl.beforeFirstNavigation + window.console.error webViewConstants.ERROR_MSG_ALREADY_NAVIGATED + @ignoreNextMutation = true + @webViewImpl.webviewNode.setAttribute @name, oldValue + return + + if newValue is 'persist:' + @validPartitionId = false + window.console.error webViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE # Sets up all of the webview attributes. WebView::setupWebViewAttributes = -> @@ -53,12 +59,14 @@ WebView::setupWebViewAttributes = -> # Initialize the attributes with special behavior (and custom attribute # objects). + @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY] = + new BooleanAttribute(webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY, this) + @attributes[webViewConstants.ATTRIBUTE_AUTOSIZE] = + new BooleanAttribute(webViewConstants.ATTRIBUTE_AUTOSIZE, this) @attributes[webViewConstants.ATTRIBUTE_PARTITION] = new Partition(this) # Initialize the remaining attributes, which have default behavior. defaultAttributes = [ - webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY - webViewConstants.ATTRIBUTE_AUTOSIZE webViewConstants.ATTRIBUTE_MAXHEIGHT webViewConstants.ATTRIBUTE_MAXWIDTH webViewConstants.ATTRIBUTE_MINHEIGHT diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index 99f555f431..21b8324316 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -27,7 +27,6 @@ class WebView @beforeFirstNavigation = true @contentWindow = null - @validPartitionId = true # Used to save some state upon deferred attachment. # If bindings is not available, we defer attachment. # This state contains whether or not the attachment request was for @@ -74,7 +73,6 @@ class WebView guestViewInternal.destroyGuest @guestInstanceId @guestInstanceId = undefined @beforeFirstNavigation = true - @validPartitionId = true @attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId = true @contentWindow = null @internalInstanceId = 0 @@ -103,10 +101,9 @@ class WebView setupAutoSizeProperties: -> for attributeName in AUTO_SIZE_ATTRIBUTES - @attributes[attributeName].setValue @webviewNode.getAttribute(attributeName) Object.defineProperty @webviewNode, attributeName, get: => @attributes[attributeName].getValue() - set: (value) => @webviewNode.setAttribute attributeName, value + set: (value) => @attributes[attributeName].setValue value enumerable: true setupWebviewNodeProperties: -> @@ -114,8 +111,7 @@ class WebView Object.defineProperty @webviewNode, webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY, get: => @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].getValue() - set: (value) => - @webviewNode.setAttribute webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY, value + set: (value) => @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].setValue value enumerable: true # We cannot use {writable: true} property descriptor because we want a @@ -129,22 +125,17 @@ class WebView Object.defineProperty @webviewNode, webViewConstants.ATTRIBUTE_PARTITION, get: => @attributes[webViewConstants.ATTRIBUTE_PARTITION].getValue() - set: (value) => - result = @attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue value - throw result.error if result.error? - @webviewNode.setAttribute webViewConstants.ATTRIBUTE_PARTITION, value + set: (value) => @attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue value enumerable: true - @attributes[webViewConstants.ATTRIBUTE_SRC].setValue @webviewNode.getAttribute(webViewConstants.ATTRIBUTE_SRC) Object.defineProperty @webviewNode, webViewConstants.ATTRIBUTE_SRC, get: => @attributes[webViewConstants.ATTRIBUTE_SRC].getValue() - set: (value) => @webviewNode.setAttribute webViewConstants.ATTRIBUTE_SRC, value + set: (value) => @attributes[webViewConstants.ATTRIBUTE_SRC].setValue value enumerable: true - @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].setValue @webviewNode.getAttribute(webViewConstants.ATTRIBUTE_HTTPREFERRER) Object.defineProperty @webviewNode, webViewConstants.ATTRIBUTE_HTTPREFERRER, get: => @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].getValue() - set: (value) => @webviewNode.setAttribute webViewConstants.ATTRIBUTE_HTTPREFERRER, value + set: (value) => @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].setValue value enumerable: true # The purpose of this mutation observer is to catch assignment to the src @@ -155,7 +146,7 @@ class WebView @srcAndPartitionObserver = new MutationObserver (mutations) => for mutation in mutations oldValue = mutation.oldValue - newValue = @webviewNode.getAttribute mutation.attributeName + newValue = @attributes[mutation.attributeName].getValue() return if oldValue isnt newValue @handleWebviewAttributeMutation mutation.attributeName, oldValue, newValue params = @@ -173,33 +164,33 @@ class WebView # a BrowserPlugin property will update the corresponding BrowserPlugin # attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more # details. - handleWebviewAttributeMutation: (name, oldValue, newValue) -> - if name in AUTO_SIZE_ATTRIBUTES - @attributes[name].setValue newValue + handleWebviewAttributeMutation: (attributeName, oldValue, newValue) -> + # Certain changes (such as internally-initiated changes) to attributes should + # not be handled normally. + if @attributes[attributeName]?.ignoreNextMutation + @attributes[attributeName].ignoreNextMutation = false + return + + if attributeName in AUTO_SIZE_ATTRIBUTES return unless @guestInstanceId - # Convert autosize attribute to boolean. - autosize = @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_AUTOSIZE guestViewInternal.setAutoSize @guestInstanceId, - enableAutoSize: autosize, + enableAutoSize: @attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue(), min: width: parseInt @attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() || 0 height: parseInt @attributes[webViewConstants.ATTRIBUTE_MINHEIGHT].getValue() || 0 max: width: parseInt @attributes[webViewConstants.ATTRIBUTE_MAXWIDTH].getValue() || 0 height: parseInt @attributes[webViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() || 0 - else if name is webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY + else if attributeName is webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY # We treat null attribute (attribute removed) and the empty string as # one case. oldValue ?= '' newValue ?= '' - return if oldValue is newValue - @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].setValue(newValue != '') - - return unless @guestInstanceId + return if oldValue is newValue and not @guestInstanceId guestViewInternal.setAllowTransparency @guestInstanceId, @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].getValue() - else if name is webViewConstants.ATTRIBUTE_HTTPREFERRER + else if attributeName is webViewConstants.ATTRIBUTE_HTTPREFERRER oldValue ?= '' newValue ?= '' @@ -208,19 +199,16 @@ class WebView @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].setValue newValue - result = {} # If the httpreferrer changes treat it as though the src changes and reload # the page with the new httpreferrer. - @parseSrcAttribute result - - throw result.error if result.error? - else if name is webViewConstants.ATTRIBUTE_SRC + @parseSrcAttribute() + else if attributeName is webViewConstants.ATTRIBUTE_SRC # We treat null attribute (attribute removed) and the empty string as # one case. oldValue ?= '' newValue ?= '' # Once we have navigated, we don't allow clearing the src attribute. - # Once enters a navigated state, it cannot be return back to a + # Once enters a navigated state, it cannot return to a # placeholder state. if newValue == '' and oldValue != '' # src attribute changes normally initiate a navigation. We suppress @@ -228,22 +216,19 @@ class WebView # on every guest-initiated navigation. @ignoreNextSrcAttributeChange = true @webviewNode.setAttribute webViewConstants.ATTRIBUTE_SRC, oldValue - @src = newValue + return + if @ignoreNextSrcAttributeChange # Don't allow the src mutation observer to see this change. @srcAndPartitionObserver.takeRecords() @ignoreNextSrcAttributeChange = false return - result = {} - @parseSrcAttribute result + @parseSrcAttribute() + else if attributeName is webViewConstants.ATTRIBUTE_PARTITION + @attributes[webViewConstants.ATTRIBUTE_PARTITION].handleMutation oldValue, newValue - throw result.error if result.error? - else if name is webViewConstants.ATTRIBUTE_PARTITION - # Note that throwing error here won't synchronously propagate. - @attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue newValue - - handleBrowserPluginAttributeMutation: (name, oldValue, newValue) -> - if name is webViewConstants.ATTRIBUTE_INTERNALINSTANCEID and !oldValue and !!newValue + handleBrowserPluginAttributeMutation: (attributeName, oldValue, newValue) -> + if attributeName is webViewConstants.ATTRIBUTE_INTERNALINSTANCEID and !oldValue and !!newValue @browserPluginNode.removeAttribute webViewConstants.ATTRIBUTE_INTERNALINSTANCEID @internalInstanceId = parseInt newValue @@ -289,7 +274,7 @@ class WebView minHeight = height minHeight = maxHeight if minHeight > maxHeight - if not @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_AUTOSIZE or + if not @attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue() or (newWidth >= minWidth and newWidth <= maxWidth and newHeight >= minHeight and @@ -307,13 +292,10 @@ class WebView hasNavigated: -> not @beforeFirstNavigation - parseSrcAttribute: (result) -> - unless @attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId - result.error = webViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE + parseSrcAttribute: -> + if not @attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId or + not @attributes[webViewConstants.ATTRIBUTE_SRC].getValue() return - @attributes[webViewConstants.ATTRIBUTE_SRC].setValue @webviewNode.getAttribute(webViewConstants.ATTRIBUTE_SRC) - - return unless @attributes[webViewConstants.ATTRIBUTE_SRC].getValue() unless @guestInstanceId? if @beforeFirstNavigation @@ -329,17 +311,12 @@ class WebView parseAttributes: -> return unless @elementAttached hasNavigated = @hasNavigated() - attributeValue = @webviewNode.getAttribute webViewConstants.ATTRIBUTE_PARTITION - result = @attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue attributeValue - @parseSrcAttribute result + @parseSrcAttribute() createGuest: -> return if @pendingGuestCreation - storagePartitionId = - @webviewNode.getAttribute(webViewConstants.ATTRIBUTE_PARTITION) or - @webviewNode[webViewConstants.ATTRIBUTE_PARTITION] params = - storagePartitionId: storagePartitionId + storagePartitionId: @attributes[webViewConstants.ATTRIBUTE_PARTITION].getValue() nodeIntegration: @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_NODEINTEGRATION plugins: @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_PLUGINS if @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_PRELOAD @@ -390,12 +367,11 @@ class WebView this.webviewNode.setAttribute webViewConstants.ATTRIBUTE_SRC, newValue onAttach: (storagePartitionId) -> - @webviewNode.setAttribute webViewConstants.ATTRIBUTE_PARTITION, storagePartitionId @attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue storagePartitionId buildAttachParams: (isNewWindow) -> - allowtransparency: @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].getValue() || false - autosize: @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_AUTOSIZE + allowtransparency: @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].getValue() + autosize: @attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue() instanceId: @viewInstanceId maxheight: parseInt @attributes[webViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() || 0 maxwidth: parseInt @attributes[webViewConstants.ATTRIBUTE_MAXWIDTH].getValue() || 0 From b6b8b936f204c04958a774857b12cf92bd216cd3 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 8 Dec 2014 17:05:57 -0800 Subject: [PATCH 13/41] Automated the definitions of webview attributes as properties on the webview node Imported from: https://chromium.googlesource.com/chromium/src/+/aef58f49f6a6157444fdf8711147bba1addef9ea%5E%21/ --- .../lib/web-view/web-view-attributes.coffee | 10 +++++-- atom/renderer/lib/web-view/web-view.coffee | 30 ++----------------- 2 files changed, 10 insertions(+), 30 deletions(-) diff --git a/atom/renderer/lib/web-view/web-view-attributes.coffee b/atom/renderer/lib/web-view/web-view-attributes.coffee index 3d96859bb5..da34a0d49b 100644 --- a/atom/renderer/lib/web-view/web-view-attributes.coffee +++ b/atom/renderer/lib/web-view/web-view-attributes.coffee @@ -15,16 +15,22 @@ class WebViewAttribute # Sets the attribute's value. setValue: (value) -> @webViewImpl.webviewNode.setAttribute(@name, value || '') + # Defines this attribute as a property on the webview node. + define: -> + Object.defineProperty @webViewImpl.webviewNode, @name, + get: => @getValue() + set: (value) => @setValue value + enumerable: true + # Called when the attribute's value changes. handleMutation: -> -# Attribute specifying whether transparency is allowed in the webview. +# An attribute that is treated as a Boolean. class BooleanAttribute extends WebViewAttribute constructor: (name, webViewImpl) -> super name, webViewImpl getValue: -> - # This attribute is treated as a boolean, and is retrieved as such. @webViewImpl.webviewNode.hasAttribute @name setValue: (value) -> diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index 21b8324316..246fc85fcf 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -99,20 +99,9 @@ class WebView validateExecuteCodeCall: -> throw new Error(webViewConstants.ERROR_MSG_CANNOT_INJECT_SCRIPT) unless @guestInstanceId - setupAutoSizeProperties: -> - for attributeName in AUTO_SIZE_ATTRIBUTES - Object.defineProperty @webviewNode, attributeName, - get: => @attributes[attributeName].getValue() - set: (value) => @attributes[attributeName].setValue value - enumerable: true - setupWebviewNodeProperties: -> - @setupAutoSizeProperties() - - Object.defineProperty @webviewNode, webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY, - get: => @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].getValue() - set: (value) => @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].setValue value - enumerable: true + for attributeName of @attributes + @attributes[attributeName].define() # We cannot use {writable: true} property descriptor because we want a # dynamic getter value. @@ -123,21 +112,6 @@ class WebView # No setter. enumerable: true - Object.defineProperty @webviewNode, webViewConstants.ATTRIBUTE_PARTITION, - get: => @attributes[webViewConstants.ATTRIBUTE_PARTITION].getValue() - set: (value) => @attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue value - enumerable: true - - Object.defineProperty @webviewNode, webViewConstants.ATTRIBUTE_SRC, - get: => @attributes[webViewConstants.ATTRIBUTE_SRC].getValue() - set: (value) => @attributes[webViewConstants.ATTRIBUTE_SRC].setValue value - enumerable: true - - Object.defineProperty @webviewNode, webViewConstants.ATTRIBUTE_HTTPREFERRER, - get: => @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].getValue() - set: (value) => @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].setValue value - enumerable: true - # The purpose of this mutation observer is to catch assignment to the src # attribute without any changes to its value. This is useful in the case # where the webview guest has crashed and navigating to the same address From 4348143fd900ab082a5d0522ff43ab4ae9d789cc Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 8 Dec 2014 17:15:50 -0800 Subject: [PATCH 14/41] Simplify web-view.coffee Imported from: https://chromium.googlesource.com/chromium/src/+/3ef1fc1b72af221a5cf8ebfd2db1ead5afda6a06%5E%21/ --- atom/renderer/lib/web-view/web-view.coffee | 33 ++++++++-------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index 246fc85fcf..91a85a8cd7 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -27,11 +27,6 @@ class WebView @beforeFirstNavigation = true @contentWindow = null - # Used to save some state upon deferred attachment. - # If bindings is not available, we defer attachment. - # This state contains whether or not the attachment request was for - # newwindow. - @deferredAttachState = null # on* Event handlers. @on = {} @@ -206,10 +201,9 @@ class WebView @browserPluginNode.removeAttribute webViewConstants.ATTRIBUTE_INTERNALINSTANCEID @internalInstanceId = parseInt newValue - if !!@guestInstanceId and @guestInstanceId != 0 - isNewWindow = if @deferredAttachState then @deferredAttachState.isNewWindow else false - params = @buildAttachParams isNewWindow - guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, params, (w) => @contentWindow = w + return unless @guestInstanceId + + guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, params, (w) => @contentWindow = w onSizeChanged: (webViewEvent) -> newWidth = webViewEvent.newWidth @@ -309,7 +303,7 @@ class WebView unless @elementAttached guestViewInternal.destroyGuest guestInstanceId return - @attachWindow guestInstanceId, false + @attachWindow guestInstanceId @pendingGuestCreation = true dispatchEvent: (webViewEvent) -> @@ -343,31 +337,26 @@ class WebView onAttach: (storagePartitionId) -> @attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue storagePartitionId - buildAttachParams: (isNewWindow) -> + buildAttachParams: -> + instanceId: @viewInstanceId + userAgentOverride: @userAgentOverride + # Attributes: allowtransparency: @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].getValue() autosize: @attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue() - instanceId: @viewInstanceId maxheight: parseInt @attributes[webViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() || 0 maxwidth: parseInt @attributes[webViewConstants.ATTRIBUTE_MAXWIDTH].getValue() || 0 minheight: parseInt @attributes[webViewConstants.ATTRIBUTE_MINHEIGHT].getValue() || 0 minwidth: parseInt @attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() || 0 - # We don't need to navigate new window from here. - src: if isNewWindow then undefined else @attributes[webViewConstants.ATTRIBUTE_SRC].getValue() - # If we have a partition from the opener, that will also be already - # set via this.onAttach(). - storagePartitionId: @attributes[webViewConstants.ATTRIBUTE_PARTITION].getValue() - userAgentOverride: @userAgentOverride + src: @attributes[webViewConstants.ATTRIBUTE_SRC].getValue() httpreferrer: @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].getValue() - attachWindow: (guestInstanceId, isNewWindow) -> + attachWindow: (guestInstanceId) -> @guestInstanceId = guestInstanceId - params = @buildAttachParams isNewWindow + params = @buildAttachParams() unless @isPluginInRenderTree() - @deferredAttachState = isNewWindow: isNewWindow return true - @deferredAttachState = null guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, params, (w) => @contentWindow = w # Registers browser plugin custom element. From ac51207860a10714af47a649ec6d654ea9ac05c6 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 8 Dec 2014 21:06:23 -0800 Subject: [PATCH 15/41] Optimized the handling of webview attribute mutation Imported from: https://chromium.googlesource.com/chromium/src/+/86dff6fc519e5db4469d89b2f56f8a1ce36d864f%5E%21/ --- .../lib/web-view/web-view-attributes.coffee | 120 +++++++++++++++--- atom/renderer/lib/web-view/web-view.coffee | 119 ++--------------- 2 files changed, 110 insertions(+), 129 deletions(-) diff --git a/atom/renderer/lib/web-view/web-view-attributes.coffee b/atom/renderer/lib/web-view/web-view-attributes.coffee index da34a0d49b..cf1c063ec8 100644 --- a/atom/renderer/lib/web-view/web-view-attributes.coffee +++ b/atom/renderer/lib/web-view/web-view-attributes.coffee @@ -1,4 +1,5 @@ WebView = require './web-view' +guestViewInternal = require './guest-view-internal' webViewConstants = require './web-view-constants' # Attribute objects. @@ -7,7 +8,9 @@ class WebViewAttribute constructor: (name, webViewImpl) -> @name = name @webViewImpl = webViewImpl - @ignoreNextMutation = false + @ignoreMutation = false + + @defineProperty() # Retrieves and returns the attribute's value. getValue: -> @webViewImpl.webviewNode.getAttribute(@name) || '' @@ -15,8 +18,14 @@ class WebViewAttribute # Sets the attribute's value. setValue: (value) -> @webViewImpl.webviewNode.setAttribute(@name, value || '') + # Changes the attribute's value without triggering its mutation handler. + setValueIgnoreMutation: (value) -> + @ignoreMutation = true + @webViewImpl.webviewNode.setAttribute(@name, value || '') + @ignoreMutation = false + # Defines this attribute as a property on the webview node. - define: -> + defineProperty: -> Object.defineProperty @webViewImpl.webviewNode, @name, get: => @getValue() set: (value) => @setValue value @@ -30,8 +39,7 @@ class BooleanAttribute extends WebViewAttribute constructor: (name, webViewImpl) -> super name, webViewImpl - getValue: -> - @webViewImpl.webviewNode.hasAttribute @name + getValue: -> @webViewImpl.webviewNode.hasAttribute @name setValue: (value) -> unless value @@ -39,8 +47,42 @@ class BooleanAttribute extends WebViewAttribute else @webViewImpl.webviewNode.setAttribute @name, '' +# Attribute that specifies whether transparency is allowed in the webview. +class AllowTransparencyAttribute extends BooleanAttribute + constructor: (webViewImpl) -> + super webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY, webViewImpl + + handleMutation: (oldValue, newValue) -> + return unless @webViewImpl.guestInstanceId + guestViewInternal.setAllowTransparency @webViewImpl.guestInstanceId, @webViewImpl.attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].getValue() + +# Attribute used to define the demension limits of autosizing. +class AutosizeDimensionAttribute extends WebViewAttribute + constructor: (name, webViewImpl) -> + super name, webViewImpl + + getValue: -> parseInt(@webViewImpl.webviewNode.getAttribute(@name)) || 0 + + handleMutation: (oldValue, newValue) -> + return unless @webViewImpl.guestInstanceId + guestViewInternal.setAutoSize @webViewImpl.guestInstanceId, + enableAutoSize: @webViewImpl.attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue() + min: + width: parseInt @webViewImpl.attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() || 0 + height: parseInt @webViewImpl.attributes[webViewConstants.ATTRIBUTE_MINHEIGHT].getValue() || 0 + max: + width: parseInt @webViewImpl.attributes[webViewConstants.ATTRIBUTE_MAXWIDTH].getValue() || 0 + height: parseInt @webViewImpl.attributes[webViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() || 0 + +# Attribute that specifies whether the webview should be autosized. +class AutosizeAttribute extends BooleanAttribute + constructor: (webViewImpl) -> + super webViewConstants.ATTRIBUTE_AUTOSIZE, webViewImpl + + handleMutation: AutosizeDimensionAttribute::handleMutation + # Attribute representing the state of the storage partition. -class Partition extends WebViewAttribute +class PartitionAttribute extends WebViewAttribute constructor: (webViewImpl) -> super webViewConstants.ATTRIBUTE_PARTITION, webViewImpl @validPartitionId = true @@ -51,35 +93,71 @@ class Partition extends WebViewAttribute # The partition cannot change if the webview has already navigated. unless @webViewImpl.beforeFirstNavigation window.console.error webViewConstants.ERROR_MSG_ALREADY_NAVIGATED - @ignoreNextMutation = true - @webViewImpl.webviewNode.setAttribute @name, oldValue + @setValueIgnoreMutation oldValue return if newValue is 'persist:' @validPartitionId = false window.console.error webViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE +# Attribute that handles the location and navigation of the webview. +class SrcAttribute extends WebViewAttribute + constructor: (webViewImpl) -> + super webViewConstants.ATTRIBUTE_SRC, webViewImpl + @setupMutationObserver() + + handleMutation: (oldValue, newValue) -> + # Once we have navigated, we don't allow clearing the src attribute. + # Once enters a navigated state, it cannot return to a + # placeholder state. + if not newValue and oldValue + # src attribute changes normally initiate a navigation. We suppress + # the next src attribute handler call to avoid reloading the page + # on every guest-initiated navigation. + @setValueIgnoreMutation oldValue + return + @webViewImpl.parseSrcAttribute() + + # The purpose of this mutation observer is to catch assignment to the src + # attribute without any changes to its value. This is useful in the case + # where the webview guest has crashed and navigating to the same address + # spawns off a new process. + setupMutationObserver: -> + @observer = new MutationObserver (mutations) => + for mutation in mutations + oldValue = mutation.oldValue + newValue = @getValue() + return if oldValue isnt newValue + @handleMutation oldValue, newValue + params = + attributes: true, + attributeOldValue: true, + attributeFilter: [@name] + @observer.observe @webViewImpl.webviewNode, params + +# Attribute specifies HTTP referrer. +class HttpReferrerAttribute extends WebViewAttribute + constructor: (webViewImpl) -> + super webViewConstants.ATTRIBUTE_HTTPREFERRER, webViewImpl + + handleMutation: (oldValue, newValue) -> + @webViewImpl.parseSrcAttribute() + # Sets up all of the webview attributes. WebView::setupWebViewAttributes = -> @attributes = {} - # Initialize the attributes with special behavior (and custom attribute - # objects). - @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY] = - new BooleanAttribute(webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY, this) - @attributes[webViewConstants.ATTRIBUTE_AUTOSIZE] = - new BooleanAttribute(webViewConstants.ATTRIBUTE_AUTOSIZE, this) - @attributes[webViewConstants.ATTRIBUTE_PARTITION] = new Partition(this) + @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY] = new AllowTransparencyAttribute(this) + @attributes[webViewConstants.ATTRIBUTE_AUTOSIZE] = new AutosizeAttribute(this) + @attributes[webViewConstants.ATTRIBUTE_PARTITION] = new PartitionAttribute(this) + @attributes[webViewConstants.ATTRIBUTE_SRC] = new SrcAttribute(this) + @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER] = new HttpReferrerAttribute(this) - # Initialize the remaining attributes, which have default behavior. - defaultAttributes = [ + autosizeAttributes = [ webViewConstants.ATTRIBUTE_MAXHEIGHT webViewConstants.ATTRIBUTE_MAXWIDTH webViewConstants.ATTRIBUTE_MINHEIGHT webViewConstants.ATTRIBUTE_MINWIDTH - webViewConstants.ATTRIBUTE_SRC - webViewConstants.ATTRIBUTE_HTTPREFERRER ] - - for attribute in defaultAttributes - @attributes[attribute] = new WebViewAttribute(attribute, this) + for attribute in autosizeAttributes + @attributes[attribute] = new AutosizeDimensionAttribute(attribute, this) diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index 91a85a8cd7..fd3984f64f 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -4,15 +4,6 @@ webViewConstants = require './web-view-constants' webFrame = require 'web-frame' remote = require 'remote' -# Attributes. -AUTO_SIZE_ATTRIBUTES = [ - webViewConstants.ATTRIBUTE_AUTOSIZE, - webViewConstants.ATTRIBUTE_MAXHEIGHT, - webViewConstants.ATTRIBUTE_MAXWIDTH, - webViewConstants.ATTRIBUTE_MINHEIGHT, - webViewConstants.ATTRIBUTE_MINWIDTH, -] - # ID generator. nextId = 0 getNextId = -> ++nextId @@ -34,13 +25,11 @@ class WebView @browserPluginNode = @createBrowserPluginNode() shadowRoot = @webviewNode.createShadowRoot() @setupWebViewAttributes() - @setupWebViewSrcAttributeMutationObserver() @setupFocusPropagation() @setupWebviewNodeProperties() @viewInstanceId = getNextId() - # UPSTREAM: new WebViewEvents(this, this.viewInstanceId); guestViewInternal.registerEvents this, @viewInstanceId shadowRoot.appendChild @browserPluginNode @@ -95,9 +84,6 @@ class WebView throw new Error(webViewConstants.ERROR_MSG_CANNOT_INJECT_SCRIPT) unless @guestInstanceId setupWebviewNodeProperties: -> - for attributeName of @attributes - @attributes[attributeName].define() - # We cannot use {writable: true} property descriptor because we want a # dynamic getter value. Object.defineProperty @webviewNode, 'contentWindow', @@ -107,94 +93,17 @@ class WebView # No setter. enumerable: true - # The purpose of this mutation observer is to catch assignment to the src - # attribute without any changes to its value. This is useful in the case - # where the webview guest has crashed and navigating to the same address - # spawns off a new process. - setupWebViewSrcAttributeMutationObserver: -> - @srcAndPartitionObserver = new MutationObserver (mutations) => - for mutation in mutations - oldValue = mutation.oldValue - newValue = @attributes[mutation.attributeName].getValue() - return if oldValue isnt newValue - @handleWebviewAttributeMutation mutation.attributeName, oldValue, newValue - params = - attributes: true, - attributeOldValue: true, - attributeFilter: [ - webViewConstants.ATTRIBUTE_SRC - webViewConstants.ATTRIBUTE_PARTITION - webViewConstants.ATTRIBUTE_HTTPREFERRER - ] - @srcAndPartitionObserver.observe @webviewNode, params - # This observer monitors mutations to attributes of the and # updates the BrowserPlugin properties accordingly. In turn, updating # a BrowserPlugin property will update the corresponding BrowserPlugin # attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more # details. handleWebviewAttributeMutation: (attributeName, oldValue, newValue) -> - # Certain changes (such as internally-initiated changes) to attributes should - # not be handled normally. - if @attributes[attributeName]?.ignoreNextMutation - @attributes[attributeName].ignoreNextMutation = false + if not @attributes[attributeName] or @attributes[attributeName].ignoreMutation return - if attributeName in AUTO_SIZE_ATTRIBUTES - return unless @guestInstanceId - guestViewInternal.setAutoSize @guestInstanceId, - enableAutoSize: @attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue(), - min: - width: parseInt @attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() || 0 - height: parseInt @attributes[webViewConstants.ATTRIBUTE_MINHEIGHT].getValue() || 0 - max: - width: parseInt @attributes[webViewConstants.ATTRIBUTE_MAXWIDTH].getValue() || 0 - height: parseInt @attributes[webViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() || 0 - else if attributeName is webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY - # We treat null attribute (attribute removed) and the empty string as - # one case. - oldValue ?= '' - newValue ?= '' - - return if oldValue is newValue and not @guestInstanceId - - guestViewInternal.setAllowTransparency @guestInstanceId, @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].getValue() - else if attributeName is webViewConstants.ATTRIBUTE_HTTPREFERRER - oldValue ?= '' - newValue ?= '' - - if newValue == '' and oldValue != '' - @webviewNode.setAttribute webViewConstants.ATTRIBUTE_HTTPREFERRER, oldValue - - @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].setValue newValue - - # If the httpreferrer changes treat it as though the src changes and reload - # the page with the new httpreferrer. - @parseSrcAttribute() - else if attributeName is webViewConstants.ATTRIBUTE_SRC - # We treat null attribute (attribute removed) and the empty string as - # one case. - oldValue ?= '' - newValue ?= '' - # Once we have navigated, we don't allow clearing the src attribute. - # Once enters a navigated state, it cannot return to a - # placeholder state. - if newValue == '' and oldValue != '' - # src attribute changes normally initiate a navigation. We suppress - # the next src attribute handler call to avoid reloading the page - # on every guest-initiated navigation. - @ignoreNextSrcAttributeChange = true - @webviewNode.setAttribute webViewConstants.ATTRIBUTE_SRC, oldValue - return - - if @ignoreNextSrcAttributeChange - # Don't allow the src mutation observer to see this change. - @srcAndPartitionObserver.takeRecords() - @ignoreNextSrcAttributeChange = false - return - @parseSrcAttribute() - else if attributeName is webViewConstants.ATTRIBUTE_PARTITION - @attributes[webViewConstants.ATTRIBUTE_PARTITION].handleMutation oldValue, newValue + # Let the changed attribute handle its own mutation; + @attributes[attributeName].handleMutation oldValue, newValue handleBrowserPluginAttributeMutation: (attributeName, oldValue, newValue) -> if attributeName is webViewConstants.ATTRIBUTE_INTERNALINSTANCEID and !oldValue and !!newValue @@ -330,25 +239,19 @@ class WebView if isTopLevel and (oldValue != newValue) # Touching the src attribute triggers a navigation. To avoid # triggering a page reload on every guest-initiated navigation, - # we use the flag ignoreNextSrcAttributeChange here. - this.ignoreNextSrcAttributeChange = true - this.webviewNode.setAttribute webViewConstants.ATTRIBUTE_SRC, newValue + # we do not handle this mutation + @attributes[webViewConstants.ATTRIBUTE_SRC].setValueIgnoreMutation newValue onAttach: (storagePartitionId) -> @attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue storagePartitionId buildAttachParams: -> - instanceId: @viewInstanceId - userAgentOverride: @userAgentOverride - # Attributes: - allowtransparency: @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].getValue() - autosize: @attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue() - maxheight: parseInt @attributes[webViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() || 0 - maxwidth: parseInt @attributes[webViewConstants.ATTRIBUTE_MAXWIDTH].getValue() || 0 - minheight: parseInt @attributes[webViewConstants.ATTRIBUTE_MINHEIGHT].getValue() || 0 - minwidth: parseInt @attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() || 0 - src: @attributes[webViewConstants.ATTRIBUTE_SRC].getValue() - httpreferrer: @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].getValue() + params = + instanceId: @viewInstanceId + userAgentOverride: @userAgentOverride + for attributeName, attribute of @attributes + params[attributeName] = attribute.getValue() + params attachWindow: (guestInstanceId) -> @guestInstanceId = guestInstanceId From 7f5fb4e6f9a9a3b82cc793eb4aeb5d8f35ac0a7d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 8 Dec 2014 21:10:59 -0800 Subject: [PATCH 16/41] Renamed "WebView" -> "WebViewImpl" in web_view.js and other files that import it Imported from: https://chromium.googlesource.com/chromium/src/+/a615ea0839c9276e80a7c0e66000dc7361ed68b6%5E%21/ --- .../renderer/lib/web-view/web-view-attributes.coffee | 4 ++-- atom/renderer/lib/web-view/web-view.coffee | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/atom/renderer/lib/web-view/web-view-attributes.coffee b/atom/renderer/lib/web-view/web-view-attributes.coffee index cf1c063ec8..a255c30669 100644 --- a/atom/renderer/lib/web-view/web-view-attributes.coffee +++ b/atom/renderer/lib/web-view/web-view-attributes.coffee @@ -1,4 +1,4 @@ -WebView = require './web-view' +WebViewImpl = require './web-view' guestViewInternal = require './guest-view-internal' webViewConstants = require './web-view-constants' @@ -144,7 +144,7 @@ class HttpReferrerAttribute extends WebViewAttribute @webViewImpl.parseSrcAttribute() # Sets up all of the webview attributes. -WebView::setupWebViewAttributes = -> +WebViewImpl::setupWebViewAttributes = -> @attributes = {} @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY] = new AllowTransparencyAttribute(this) diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index fd3984f64f..577313bff9 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -9,7 +9,7 @@ nextId = 0 getNextId = -> ++nextId # Represents the internal state of the WebView node. -class WebView +class WebViewImpl constructor: (@webviewNode) -> v8Util.setHiddenValue @webviewNode, 'internal', this @attached = false @@ -37,7 +37,7 @@ class WebView createBrowserPluginNode: -> # We create BrowserPlugin as a custom element in order to observe changes # to attributes synchronously. - browserPluginNode = new WebView.BrowserPlugin() + browserPluginNode = new WebViewImpl.BrowserPlugin() v8Util.setHiddenValue browserPluginNode, 'internal', this browserPluginNode @@ -282,7 +282,7 @@ registerBrowserPluginElement = -> # Load the plugin immediately. unused = this.nonExistentAttribute - WebView.BrowserPlugin = webFrame.registerEmbedderCustomElement 'browserplugin', + WebViewImpl.BrowserPlugin = webFrame.registerEmbedderCustomElement 'browserplugin', extends: 'object', prototype: proto delete proto.createdCallback @@ -295,7 +295,7 @@ registerWebViewElement = -> proto = Object.create HTMLObjectElement.prototype proto.createdCallback = -> - new WebView(this) + new WebViewImpl(this) proto.attributeChangedCallback = (name, oldValue, newValue) -> internal = v8Util.getHiddenValue this, 'internal' @@ -342,7 +342,7 @@ registerWebViewElement = -> "getId" ] - # Forward proto.foo* method calls to WebView.foo*. + # Forward proto.foo* method calls to WebViewImpl.foo*. createHandler = (m) -> (args...) -> internal = v8Util.getHiddenValue this, 'internal' @@ -367,4 +367,4 @@ listener = (event) -> window.removeEventListener event.type, listener, useCapture window.addEventListener 'readystatechange', listener, true -module.exports = WebView +module.exports = WebViewImpl From cbafac774e5e9a74d67315aa8dd58af9fb1cef7f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 8 Dec 2014 21:15:18 -0800 Subject: [PATCH 17/41] Various webview cleanup Imported from: https://chromium.googlesource.com/chromium/src/+/848f1ed0482838d44ffd0bbbd3b8db0e5b6362c6%5E%21/ --- atom/renderer/lib/web-view/web-view.coffee | 53 +++------------------- 1 file changed, 6 insertions(+), 47 deletions(-) diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index 577313bff9..a0087826e6 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -41,9 +41,6 @@ class WebViewImpl v8Util.setHiddenValue browserPluginNode, 'internal', this browserPluginNode - getGuestInstanceId: -> - @guestInstanceId - # Resets some state upon reattaching element to the DOM. reset: -> # If guestInstanceId is defined then the has navigated and has @@ -79,10 +76,6 @@ class WebViewImpl # Blur the BrowserPlugin when the loses focus. @browserPluginNode.blur() - # Validation helper function for executeScript() and insertCSS(). - validateExecuteCodeCall: -> - throw new Error(webViewConstants.ERROR_MSG_CANNOT_INJECT_SCRIPT) unless @guestInstanceId - setupWebviewNodeProperties: -> # We cannot use {writable: true} property descriptor because we want a # dynamic getter value. @@ -125,31 +118,10 @@ class WebViewImpl # Check the current bounds to make sure we do not resize # outside of current constraints. - if node.hasAttribute(webViewConstants.ATTRIBUTE_MAXWIDTH) and - node[webViewConstants.ATTRIBUTE_MAXWIDTH] - maxWidth = node[webViewConstants.ATTRIBUTE_MAXWIDTH] - else - maxWidth = width - - if node.hasAttribute(webViewConstants.ATTRIBUTE_MINWIDTH) and - node[webViewConstants.ATTRIBUTE_MINWIDTH] - minWidth = node[webViewConstants.ATTRIBUTE_MINWIDTH] - else - minWidth = width - minWidth = maxWidth if minWidth > maxWidth - - if node.hasAttribute(webViewConstants.ATTRIBUTE_MAXHEIGHT) and - node[webViewConstants.ATTRIBUTE_MAXHEIGHT] - maxHeight = node[webViewConstants.ATTRIBUTE_MAXHEIGHT] - else - maxHeight = height - - if node.hasAttribute(webViewConstants.ATTRIBUTE_MINHEIGHT) and - node[webViewConstants.ATTRIBUTE_MINHEIGHT] - minHeight = node[webViewConstants.ATTRIBUTE_MINHEIGHT] - else - minHeight = height - minHeight = maxHeight if minHeight > maxHeight + maxWidth = @attributes[webViewConstants.ATTRIBUTE_MAXWIDTH].getValue() | width + maxHeight = @attributes[webViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() | width + minWidth = @attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() | width + minHeight = @attributes[webViewConstants.ATTRIBUTE_MINHEIGHT].getValue() | width if not @attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue() or (newWidth >= minWidth and @@ -162,13 +134,6 @@ class WebViewImpl # changed. @dispatchEvent webViewEvent - # Returns if is in the render tree. - isPluginInRenderTree: -> - !!@internalInstanceId && @internalInstanceId != 0 - - hasNavigated: -> - not @beforeFirstNavigation - parseSrcAttribute: -> if not @attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId or not @attributes[webViewConstants.ATTRIBUTE_SRC].getValue() @@ -185,11 +150,6 @@ class WebViewImpl urlOptions = if httpreferrer then {httpreferrer} else {} remote.getGuestWebContents(@guestInstanceId).loadUrl @attributes[webViewConstants.ATTRIBUTE_SRC].getValue(), urlOptions - parseAttributes: -> - return unless @elementAttached - hasNavigated = @hasNavigated() - @parseSrcAttribute() - createGuest: -> return if @pendingGuestCreation params = @@ -257,8 +217,7 @@ class WebViewImpl @guestInstanceId = guestInstanceId params = @buildAttachParams() - unless @isPluginInRenderTree() - return true + return true unless @internalInstanceId guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, params, (w) => @contentWindow = w @@ -313,7 +272,7 @@ registerWebViewElement = -> return unless internal unless internal.elementAttached internal.elementAttached = true - internal.parseAttributes() + internal.parseSrcAttribute() # Public-facing API methods. methods = [ From 9fcb6b2cd196914bd1b7e166a9467ec8746070b1 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 8 Dec 2014 21:35:10 -0800 Subject: [PATCH 18/41] Moved parseSrcAttribute() into the SrcAttribute object as parse() Imported from: https://chromium.googlesource.com/chromium/src/+/3bc15760f9c7fb79cb3dd6064781c26ebbe1d5af%5E%21/ --- .../lib/web-view/web-view-attributes.coffee | 24 ++++++++++++++++--- atom/renderer/lib/web-view/web-view.coffee | 18 +------------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/atom/renderer/lib/web-view/web-view-attributes.coffee b/atom/renderer/lib/web-view/web-view-attributes.coffee index a255c30669..93d38495a8 100644 --- a/atom/renderer/lib/web-view/web-view-attributes.coffee +++ b/atom/renderer/lib/web-view/web-view-attributes.coffee @@ -1,6 +1,7 @@ WebViewImpl = require './web-view' guestViewInternal = require './guest-view-internal' webViewConstants = require './web-view-constants' +remote = require 'remote' # Attribute objects. # Default implementation of a WebView attribute. @@ -54,7 +55,7 @@ class AllowTransparencyAttribute extends BooleanAttribute handleMutation: (oldValue, newValue) -> return unless @webViewImpl.guestInstanceId - guestViewInternal.setAllowTransparency @webViewImpl.guestInstanceId, @webViewImpl.attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].getValue() + guestViewInternal.setAllowTransparency @webViewImpl.guestInstanceId, @getValue() # Attribute used to define the demension limits of autosizing. class AutosizeDimensionAttribute extends WebViewAttribute @@ -116,7 +117,7 @@ class SrcAttribute extends WebViewAttribute # on every guest-initiated navigation. @setValueIgnoreMutation oldValue return - @webViewImpl.parseSrcAttribute() + @parse() # The purpose of this mutation observer is to catch assignment to the src # attribute without any changes to its value. This is useful in the case @@ -135,13 +136,30 @@ class SrcAttribute extends WebViewAttribute attributeFilter: [@name] @observer.observe @webViewImpl.webviewNode, params + parse: -> + if not @webViewImpl.elementAttached or + not @webViewImpl.attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId or + not @.getValue() + return + + unless @webViewImpl.guestInstanceId? + if @webViewImpl.beforeFirstNavigation + @webViewImpl.beforeFirstNavigation = false + @webViewImpl.createGuest() + return + + # Navigate to |this.src|. + httpreferrer = @webViewImpl.attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].getValue() + urlOptions = if httpreferrer then {httpreferrer} else {} + remote.getGuestWebContents(@webViewImpl.guestInstanceId).loadUrl @getValue(), urlOptions + # Attribute specifies HTTP referrer. class HttpReferrerAttribute extends WebViewAttribute constructor: (webViewImpl) -> super webViewConstants.ATTRIBUTE_HTTPREFERRER, webViewImpl handleMutation: (oldValue, newValue) -> - @webViewImpl.parseSrcAttribute() + SrcAttribute::parse.call this # Sets up all of the webview attributes. WebViewImpl::setupWebViewAttributes = -> diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index a0087826e6..1ad9ba0f66 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -134,22 +134,6 @@ class WebViewImpl # changed. @dispatchEvent webViewEvent - parseSrcAttribute: -> - if not @attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId or - not @attributes[webViewConstants.ATTRIBUTE_SRC].getValue() - return - - unless @guestInstanceId? - if @beforeFirstNavigation - @beforeFirstNavigation = false - @createGuest() - return - - # Navigate to |this.src|. - httpreferrer = @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].getValue() - urlOptions = if httpreferrer then {httpreferrer} else {} - remote.getGuestWebContents(@guestInstanceId).loadUrl @attributes[webViewConstants.ATTRIBUTE_SRC].getValue(), urlOptions - createGuest: -> return if @pendingGuestCreation params = @@ -272,7 +256,7 @@ registerWebViewElement = -> return unless internal unless internal.elementAttached internal.elementAttached = true - internal.parseSrcAttribute() + internal.attributes[webViewConstants.ATTRIBUTE_SRC].parse() # Public-facing API methods. methods = [ From 68381e1b76e32563ea75358510fd7ae51419e5f6 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 9 Dec 2014 14:38:43 -0800 Subject: [PATCH 19/41] Use element instant id for GetGuestByInstanceID --- atom/browser/api/atom_api_web_contents.cc | 8 ++++ atom/browser/api/atom_api_web_contents.h | 33 +++++++++-------- atom/browser/lib/guest-view-manager.coffee | 14 +++++-- atom/browser/web_view/web_view_manager.cc | 43 ++++++++++++++++++---- atom/browser/web_view/web_view_manager.h | 41 ++++++++++++++++++--- atom/renderer/lib/web-view/web-view.coffee | 26 ++++++------- 6 files changed, 119 insertions(+), 46 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 19b6d3276a..7bd1095b8a 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -12,6 +12,7 @@ #include "atom/common/native_mate_converters/value_converter.h" #include "base/strings/utf_string_conversions.h" #include "brightray/browser/inspectable_web_contents.h" +#include "content/public/browser/navigation_details.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" @@ -190,6 +191,13 @@ void WebContents::DidGetRedirectForResourceRequest( Emit("did-get-redirect-request", args); } +void WebContents::DidNavigateMainFrame( + const content::LoadCommittedDetails& details, + const content::FrameNavigateParams& params) { + if (details.is_navigation_to_different_page()) + Emit("did-navigate-to-different-page"); +} + bool WebContents::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(WebContents, message) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 8371a65560..4bb798c90d 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -118,24 +118,25 @@ class WebContents : public mate::EventEmitter, const content::NativeWebKeyboardEvent& event) override; // content::WebContentsObserver: - virtual void RenderViewDeleted(content::RenderViewHost*) override; - virtual void RenderProcessGone(base::TerminationStatus status) override; - virtual void DidFinishLoad(content::RenderFrameHost* render_frame_host, - const GURL& validated_url) override; - virtual void DidFailLoad(content::RenderFrameHost* render_frame_host, - const GURL& validated_url, - int error_code, - const base::string16& error_description) override; - virtual void DidStartLoading( - content::RenderViewHost* render_view_host) override; - virtual void DidStopLoading( - content::RenderViewHost* render_view_host) override; - virtual void DidGetRedirectForResourceRequest( + void RenderViewDeleted(content::RenderViewHost*) override; + void RenderProcessGone(base::TerminationStatus status) override; + void DidFinishLoad(content::RenderFrameHost* render_frame_host, + const GURL& validated_url) override; + void DidFailLoad(content::RenderFrameHost* render_frame_host, + const GURL& validated_url, + int error_code, + const base::string16& error_description) override; + void DidStartLoading(content::RenderViewHost* render_view_host) override; + void DidStopLoading(content::RenderViewHost* render_view_host) override; + void DidGetRedirectForResourceRequest( content::RenderViewHost* render_view_host, const content::ResourceRedirectDetails& details) override; - virtual bool OnMessageReceived(const IPC::Message& message) override; - virtual void RenderViewReady() override; - virtual void WebContentsDestroyed() override; + void DidNavigateMainFrame( + const content::LoadCommittedDetails& details, + const content::FrameNavigateParams& params) override; + bool OnMessageReceived(const IPC::Message& message) override; + void RenderViewReady() override; + void WebContentsDestroyed() override; // content::BrowserPluginGuestDelegate: void DidAttach(int guest_proxy_routing_id) final; diff --git a/atom/browser/lib/guest-view-manager.coffee b/atom/browser/lib/guest-view-manager.coffee index 4f2af53f57..eef36f1fa2 100644 --- a/atom/browser/lib/guest-view-manager.coffee +++ b/atom/browser/lib/guest-view-manager.coffee @@ -35,12 +35,13 @@ createGuest = (embedder, params) -> guestInstanceId: id storagePartitionId: params.storagePartitionId guestInstances[id] = {guest, embedder} - preload = params.preload ? '' - webViewManager.addGuest id, embedder, guest, params.nodeIntegration, params.plugins, preload - # Destroy guest when the embedder is gone. - embedder.once 'render-view-deleted', -> + # Destroy guest when the embedder is gone or navigated. + destroyEvents = ['destroyed', 'crashed', 'did-navigate-to-different-page'] + destroy = -> destroyGuest id if guestInstances[id]? + embedder.removeListener event, destroy for event in destroyEvents + embedder.once event, destroy for event in destroyEvents # Init guest web view after attached. guest.once 'did-attach', -> @@ -85,6 +86,11 @@ attachGuest = (embedder, elementInstanceId, guestInstanceId, params) -> return unless guestInstances[oldGuestInstanceId]? destroyGuest oldGuestInstanceId + webViewManager.addGuest guestInstanceId, elementInstanceId, embedder, guest, + nodeIntegration: params.nodeIntegration + plugins: params.plugins + preloadUrl: params.preload ? '' + guest.attachParams = params embedderElementsMap[key] = guestInstanceId reverseEmbedderElementsMap[guestInstanceId] = key diff --git a/atom/browser/web_view/web_view_manager.cc b/atom/browser/web_view/web_view_manager.cc index bc308debad..032be04e78 100644 --- a/atom/browser/web_view/web_view_manager.cc +++ b/atom/browser/web_view/web_view_manager.cc @@ -32,6 +32,19 @@ struct Converter { } }; +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, v8::Handle val, + atom::WebViewManager::WebViewOptions* out) { + Dictionary options; + if (!ConvertFromV8(isolate, val, &options)) + return false; + return options.Get("nodeIntegration", &(out->node_integration)) && + options.Get("plugins", &(out->plugins)) && + options.Get("preloadUrl", &(out->preload_url)); + } +}; + } // namespace mate namespace atom { @@ -43,17 +56,16 @@ WebViewManager::~WebViewManager() { } void WebViewManager::AddGuest(int guest_instance_id, + int element_instance_id, content::WebContents* embedder, content::WebContents* web_contents, - bool node_integration, - bool plugins, - const GURL& preload_url) { + const WebViewOptions& options) { web_contents_map_[guest_instance_id] = { web_contents, embedder }; WebViewRendererState::WebViewInfo web_view_info = { - guest_instance_id, node_integration, plugins + guest_instance_id, options.node_integration, options.plugins }; - net::FileURLToFilePath(preload_url, &web_view_info.preload_script); + net::FileURLToFilePath(options.preload_url, &web_view_info.preload_script); content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, @@ -61,6 +73,10 @@ void WebViewManager::AddGuest(int guest_instance_id, base::Unretained(WebViewRendererState::GetInstance()), web_contents->GetRenderProcessHost()->GetID(), web_view_info)); + + // Map the element in embedder to guest. + ElementInstanceKey key(embedder, element_instance_id); + element_instance_id_to_guest_map_[key] = guest_instance_id; } void WebViewManager::RemoveGuest(int guest_instance_id) { @@ -71,13 +87,24 @@ void WebViewManager::RemoveGuest(int guest_instance_id) { &WebViewRendererState::RemoveGuest, base::Unretained(WebViewRendererState::GetInstance()), web_contents->GetRenderProcessHost()->GetID())); - web_contents_map_.erase(guest_instance_id); + + // Remove the record of element in embedder too. + for (const auto& element : element_instance_id_to_guest_map_) + if (element.second == guest_instance_id) { + element_instance_id_to_guest_map_.erase(element.first); + break; + } } content::WebContents* WebViewManager::GetGuestByInstanceID( - content::WebContents* embedder_web_contents, - int guest_instance_id) { + content::WebContents* embedder, + int element_instance_id) { + ElementInstanceKey key(embedder, element_instance_id); + if (!ContainsKey(element_instance_id_to_guest_map_, key)) + return nullptr; + + int guest_instance_id = element_instance_id_to_guest_map_[key]; if (ContainsKey(web_contents_map_, guest_instance_id)) return web_contents_map_[guest_instance_id].web_contents; else diff --git a/atom/browser/web_view/web_view_manager.h b/atom/browser/web_view/web_view_manager.h index fb118251e6..e14d31cec0 100644 --- a/atom/browser/web_view/web_view_manager.h +++ b/atom/browser/web_view/web_view_manager.h @@ -21,20 +21,25 @@ class WebViewManager : public content::BrowserPluginGuestManager { explicit WebViewManager(content::BrowserContext* context); virtual ~WebViewManager(); + struct WebViewOptions { + bool node_integration; + bool plugins; + GURL preload_url; + }; + void AddGuest(int guest_instance_id, + int element_instance_id, content::WebContents* embedder, content::WebContents* web_contents, - bool node_integration, - bool plugins, - const GURL& preload_url); + const WebViewOptions& options); void RemoveGuest(int guest_instance_id); protected: // content::BrowserPluginGuestManager: content::WebContents* GetGuestByInstanceID( content::WebContents* embedder_web_contents, - int browser_plugin_instance_id) override; - bool ForEachGuest(content::WebContents* embedder_web_contents, + int element_instance_id) override; + bool ForEachGuest(content::WebContents* embedder, const GuestCallback& callback) override; private: @@ -44,6 +49,32 @@ class WebViewManager : public content::BrowserPluginGuestManager { }; std::map web_contents_map_; + struct ElementInstanceKey { + content::WebContents* owner_web_contents; + int element_instance_id; + + ElementInstanceKey() + : owner_web_contents(nullptr), + element_instance_id(0) {} + + ElementInstanceKey(content::WebContents* owner_web_contents, + int element_instance_id) + : owner_web_contents(owner_web_contents), + element_instance_id(element_instance_id) {} + + bool operator<(const ElementInstanceKey& other) const { + if (owner_web_contents != other.owner_web_contents) + return owner_web_contents < other.owner_web_contents; + return element_instance_id < other.element_instance_id; + } + + bool operator==(const ElementInstanceKey& other) const { + return (owner_web_contents == other.owner_web_contents) && + (element_instance_id == other.element_instance_id); + } + }; + std::map element_instance_id_to_guest_map_; + DISALLOW_COPY_AND_ASSIGN(WebViewManager); }; diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index 1ad9ba0f66..a68f8e728d 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -138,19 +138,6 @@ class WebViewImpl return if @pendingGuestCreation params = storagePartitionId: @attributes[webViewConstants.ATTRIBUTE_PARTITION].getValue() - nodeIntegration: @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_NODEINTEGRATION - plugins: @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_PLUGINS - if @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_PRELOAD - preload = @webviewNode.getAttribute webViewConstants.ATTRIBUTE_PRELOAD - # Get the full path. - a = document.createElement 'a' - a.href = preload - params.preload = a.href - # Only support file: or asar: protocol. - protocol = params.preload.substr 0, 5 - unless protocol in ['file:', 'asar:'] - delete params.preload - console.error webViewConstants.ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE guestViewInternal.createGuest 'webview', params, (guestInstanceId) => @pendingGuestCreation = false unless @elementAttached @@ -193,8 +180,21 @@ class WebViewImpl params = instanceId: @viewInstanceId userAgentOverride: @userAgentOverride + nodeIntegration: @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_NODEINTEGRATION + plugins: @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_PLUGINS for attributeName, attribute of @attributes params[attributeName] = attribute.getValue() + if @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_PRELOAD + preload = @webviewNode.getAttribute webViewConstants.ATTRIBUTE_PRELOAD + # Get the full path. + a = document.createElement 'a' + a.href = preload + params.preload = a.href + # Only support file: or asar: protocol. + protocol = params.preload.substr 0, 5 + unless protocol in ['file:', 'asar:'] + delete params.preload + console.error webViewConstants.ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE params attachWindow: (guestInstanceId) -> From 9d23cce2b6b088331d28d4c925f3bf5036728dd1 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 9 Dec 2014 14:51:35 -0800 Subject: [PATCH 20/41] Move "nodeintegration" and "plugins" to web-view-attributes --- atom/browser/lib/guest-view-manager.coffee | 2 +- atom/renderer/lib/web-view/web-view-attributes.coffee | 2 ++ atom/renderer/lib/web-view/web-view.coffee | 2 -- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/atom/browser/lib/guest-view-manager.coffee b/atom/browser/lib/guest-view-manager.coffee index eef36f1fa2..d5422c1b40 100644 --- a/atom/browser/lib/guest-view-manager.coffee +++ b/atom/browser/lib/guest-view-manager.coffee @@ -87,7 +87,7 @@ attachGuest = (embedder, elementInstanceId, guestInstanceId, params) -> destroyGuest oldGuestInstanceId webViewManager.addGuest guestInstanceId, elementInstanceId, embedder, guest, - nodeIntegration: params.nodeIntegration + nodeIntegration: params.nodeintegration plugins: params.plugins preloadUrl: params.preload ? '' diff --git a/atom/renderer/lib/web-view/web-view-attributes.coffee b/atom/renderer/lib/web-view/web-view-attributes.coffee index 93d38495a8..9df67251a0 100644 --- a/atom/renderer/lib/web-view/web-view-attributes.coffee +++ b/atom/renderer/lib/web-view/web-view-attributes.coffee @@ -170,6 +170,8 @@ WebViewImpl::setupWebViewAttributes = -> @attributes[webViewConstants.ATTRIBUTE_PARTITION] = new PartitionAttribute(this) @attributes[webViewConstants.ATTRIBUTE_SRC] = new SrcAttribute(this) @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER] = new HttpReferrerAttribute(this) + @attributes[webViewConstants.ATTRIBUTE_NODEINTEGRATION] = new BooleanAttribute(webViewConstants.ATTRIBUTE_NODEINTEGRATION, this) + @attributes[webViewConstants.ATTRIBUTE_PLUGINS] = new BooleanAttribute(webViewConstants.ATTRIBUTE_PLUGINS, this) autosizeAttributes = [ webViewConstants.ATTRIBUTE_MAXHEIGHT diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index a68f8e728d..89a0d4488d 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -180,8 +180,6 @@ class WebViewImpl params = instanceId: @viewInstanceId userAgentOverride: @userAgentOverride - nodeIntegration: @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_NODEINTEGRATION - plugins: @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_PLUGINS for attributeName, attribute of @attributes params[attributeName] = attribute.getValue() if @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_PRELOAD From 7d1830d014c7c45f32aa38d57745289b994c498e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 9 Dec 2014 15:49:17 -0800 Subject: [PATCH 21/41] Upgrade node to bump node module version --- vendor/node | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/node b/vendor/node index b1d7464f1c..c8a1feaf57 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit b1d7464f1c05456027d41fa97384765bc1790212 +Subproject commit c8a1feaf57cf32a893395b255df7a8471e42a822 From e3ba17f2d32f8dfc89a684266f0d0a565fdaa7fc Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 9 Dec 2014 16:37:05 -0800 Subject: [PATCH 22/41] linux: Disable warnings for g_settings_list_schemas --- atom.gyp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/atom.gyp b/atom.gyp index d04966ae4e..41e045ea2f 100644 --- a/atom.gyp +++ b/atom.gyp @@ -529,6 +529,8 @@ 'defines': [ # This is defined in skia/skia_common.gypi. 'SK_SUPPORT_LEGACY_GETTOPDEVICE', + # Disable warnings for g_settings_list_schemas. + 'GLIB_DISABLE_DEPRECATION_WARNINGS', ], 'sources': [ '<@(lib_sources)', From e58b3ddc8658a30a75d892f3180eb25c536bd5f5 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 9 Dec 2014 16:37:40 -0800 Subject: [PATCH 23/41] Bump Chrome version --- atom/common/chrome_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/common/chrome_version.h b/atom/common/chrome_version.h index 4b8494e871..e684321e17 100644 --- a/atom/common/chrome_version.h +++ b/atom/common/chrome_version.h @@ -8,7 +8,7 @@ #ifndef ATOM_COMMON_CHROME_VERSION_H_ #define ATOM_COMMON_CHROME_VERSION_H_ -#define CHROME_VERSION_STRING "38.0.2125.101" +#define CHROME_VERSION_STRING "39.0.2171.65" #define CHROME_VERSION "v" CHROME_VERSION_STRING #endif // ATOM_COMMON_CHROME_VERSION_H_ From 22c4911b589364a2864fac772f3ad662d813ec13 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 9 Dec 2014 16:51:27 -0800 Subject: [PATCH 24/41] linux: GTK+ status icon has come back --- atom.gyp | 4 - atom/browser/ui/tray_icon.cc | 3 + atom/browser/ui/tray_icon.h | 2 +- atom/browser/ui/tray_icon_gtk.cc | 4 - atom/browser/ui/tray_icon_gtk.h | 1 - .../ui/libgtk2ui/app_indicator_icon_menu.cc | 123 ------------------ .../ui/libgtk2ui/app_indicator_icon_menu.h | 66 ---------- .../browser/ui/libgtk2ui/gtk2_status_icon.cc | 80 ------------ .../browser/ui/libgtk2ui/gtk2_status_icon.h | 61 --------- 9 files changed, 4 insertions(+), 340 deletions(-) delete mode 100644 chromium_src/chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.cc delete mode 100644 chromium_src/chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.h delete mode 100644 chromium_src/chrome/browser/ui/libgtk2ui/gtk2_status_icon.cc delete mode 100644 chromium_src/chrome/browser/ui/libgtk2ui/gtk2_status_icon.h diff --git a/atom.gyp b/atom.gyp index 41e045ea2f..d835437c87 100644 --- a/atom.gyp +++ b/atom.gyp @@ -309,10 +309,6 @@ 'chromium_src/chrome/browser/ui/cocoa/color_chooser_mac.mm', 'chromium_src/chrome/browser/ui/views/color_chooser_aura.cc', 'chromium_src/chrome/browser/ui/views/color_chooser_aura.h', - 'chromium_src/chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.cc', - 'chromium_src/chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.h', - 'chromium_src/chrome/browser/ui/libgtk2ui/gtk2_status_icon.cc', - 'chromium_src/chrome/browser/ui/libgtk2ui/gtk2_status_icon.h', 'chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc', 'chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h', 'chromium_src/chrome/common/print_messages.cc', diff --git a/atom/browser/ui/tray_icon.cc b/atom/browser/ui/tray_icon.cc index a59c0c7b8c..c8fb40902d 100644 --- a/atom/browser/ui/tray_icon.cc +++ b/atom/browser/ui/tray_icon.cc @@ -12,6 +12,9 @@ TrayIcon::TrayIcon() { TrayIcon::~TrayIcon() { } +void TrayIcon::SetPressedImage(const gfx::ImageSkia& image) { +} + void TrayIcon::SetTitle(const std::string& title) { } diff --git a/atom/browser/ui/tray_icon.h b/atom/browser/ui/tray_icon.h index 83ee98e757..a27ea82f22 100644 --- a/atom/browser/ui/tray_icon.h +++ b/atom/browser/ui/tray_icon.h @@ -23,7 +23,7 @@ class TrayIcon { virtual void SetImage(const gfx::ImageSkia& image) = 0; // Sets the image associated with this status icon when pressed. - virtual void SetPressedImage(const gfx::ImageSkia& image) = 0; + virtual void SetPressedImage(const gfx::ImageSkia& image); // Sets the hover text for this status icon. This is also used as the label // for the menu item which is created as a replacement for the status icon diff --git a/atom/browser/ui/tray_icon_gtk.cc b/atom/browser/ui/tray_icon_gtk.cc index b853453da4..c7a56ddb03 100644 --- a/atom/browser/ui/tray_icon_gtk.cc +++ b/atom/browser/ui/tray_icon_gtk.cc @@ -32,10 +32,6 @@ void TrayIconGtk::SetImage(const gfx::ImageSkia& image) { icon_->set_delegate(this); } -void TrayIconGtk::SetPressedImage(const gfx::ImageSkia& image) { - icon_->SetPressedImage(image); -} - void TrayIconGtk::SetToolTip(const std::string& tool_tip) { icon_->SetToolTip(base::UTF8ToUTF16(tool_tip)); } diff --git a/atom/browser/ui/tray_icon_gtk.h b/atom/browser/ui/tray_icon_gtk.h index e8eec3fda0..5027a2d448 100644 --- a/atom/browser/ui/tray_icon_gtk.h +++ b/atom/browser/ui/tray_icon_gtk.h @@ -24,7 +24,6 @@ class TrayIconGtk : public TrayIcon, // TrayIcon: virtual void SetImage(const gfx::ImageSkia& image) OVERRIDE; - virtual void SetPressedImage(const gfx::ImageSkia& image) OVERRIDE; virtual void SetToolTip(const std::string& tool_tip) OVERRIDE; virtual void SetContextMenu(ui::SimpleMenuModel* menu_model) OVERRIDE; diff --git a/chromium_src/chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.cc b/chromium_src/chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.cc deleted file mode 100644 index 151117314c..0000000000 --- a/chromium_src/chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.cc +++ /dev/null @@ -1,123 +0,0 @@ -// 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. - -#include "chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.h" - -#include - -#include "base/bind.h" -#include "base/debug/leak_annotations.h" -#include "chrome/browser/ui/libgtk2ui/menu_util.h" -#include "ui/base/models/menu_model.h" - -namespace libgtk2ui { - -AppIndicatorIconMenu::AppIndicatorIconMenu(ui::MenuModel* model) - : menu_model_(model), - click_action_replacement_menu_item_added_(false), - gtk_menu_(NULL), - block_activation_(false) { - { - ANNOTATE_SCOPED_MEMORY_LEAK; // http://crbug.com/378770 - gtk_menu_ = gtk_menu_new(); - } - g_object_ref_sink(gtk_menu_); - if (menu_model_) { - BuildSubmenuFromModel(menu_model_, - gtk_menu_, - G_CALLBACK(OnMenuItemActivatedThunk), - &block_activation_, - this); - Refresh(); - } -} - -AppIndicatorIconMenu::~AppIndicatorIconMenu() { - gtk_widget_destroy(gtk_menu_); - g_object_unref(gtk_menu_); -} - -void AppIndicatorIconMenu::UpdateClickActionReplacementMenuItem( - const char* label, - const base::Closure& callback) { - click_action_replacement_callback_ = callback; - - if (click_action_replacement_menu_item_added_) { - GList* children = gtk_container_get_children(GTK_CONTAINER(gtk_menu_)); - for (GList* child = children; child; child = g_list_next(child)) { - if (g_object_get_data(G_OBJECT(child->data), "click-action-item") != - NULL) { - gtk_menu_item_set_label(GTK_MENU_ITEM(child->data), label); - break; - } - } - g_list_free(children); - } else { - click_action_replacement_menu_item_added_ = true; - - // If |menu_model_| is non empty, add a separator to separate the - // "click action replacement menu item" from the other menu items. - if (menu_model_ && menu_model_->GetItemCount() > 0) { - GtkWidget* menu_item = gtk_separator_menu_item_new(); - gtk_widget_show(menu_item); - gtk_menu_shell_prepend(GTK_MENU_SHELL(gtk_menu_), menu_item); - } - - GtkWidget* menu_item = gtk_menu_item_new_with_mnemonic(label); - g_object_set_data( - G_OBJECT(menu_item), "click-action-item", GINT_TO_POINTER(1)); - g_signal_connect(menu_item, - "activate", - G_CALLBACK(OnClickActionReplacementMenuItemActivatedThunk), - this); - gtk_widget_show(menu_item); - gtk_menu_shell_prepend(GTK_MENU_SHELL(gtk_menu_), menu_item); - } -} - -void AppIndicatorIconMenu::Refresh() { - gtk_container_foreach( - GTK_CONTAINER(gtk_menu_), SetMenuItemInfo, &block_activation_); -} - -GtkMenu* AppIndicatorIconMenu::GetGtkMenu() { - return GTK_MENU(gtk_menu_); -} - - -void AppIndicatorIconMenu::OnClickActionReplacementMenuItemActivated( - GtkWidget* menu_item) { - click_action_replacement_callback_.Run(); -} - -void AppIndicatorIconMenu::OnMenuItemActivated(GtkWidget* menu_item) { - if (block_activation_) - return; - - ui::MenuModel* model = ModelForMenuItem(GTK_MENU_ITEM(menu_item)); - if (!model) { - // There won't be a model for "native" submenus like the "Input Methods" - // context menu. We don't need to handle activation messages for submenus - // anyway, so we can just return here. - DCHECK(gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu_item))); - return; - } - - // The activate signal is sent to radio items as they get deselected; - // ignore it in this case. - if (GTK_IS_RADIO_MENU_ITEM(menu_item) && - !gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_item))) { - return; - } - - int id; - if (!GetMenuItemID(menu_item, &id)) - return; - - // The menu item can still be activated by hotkeys even if it is disabled. - if (menu_model_->IsEnabledAt(id)) - ExecuteCommand(model, id); -} - -} // namespace libgtk2ui diff --git a/chromium_src/chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.h b/chromium_src/chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.h deleted file mode 100644 index a204710f9c..0000000000 --- a/chromium_src/chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.h +++ /dev/null @@ -1,66 +0,0 @@ -// 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. - -#ifndef CHROME_BROWSER_UI_LIBGTK2UI_APP_INDICATOR_ICON_MENU_H_ -#define CHROME_BROWSER_UI_LIBGTK2UI_APP_INDICATOR_ICON_MENU_H_ - -#include "base/callback.h" -#include "chrome/browser/ui/libgtk2ui/gtk2_signal.h" - -typedef struct _GtkMenu GtkMenu; -typedef struct _GtkWidget GtkWidget; - -namespace ui { -class MenuModel; -} - -namespace libgtk2ui { - -// The app indicator icon's menu. -class AppIndicatorIconMenu { - public: - explicit AppIndicatorIconMenu(ui::MenuModel* model); - virtual ~AppIndicatorIconMenu(); - - // Sets a menu item at the top of |gtk_menu_| as a replacement for the app - // indicator icon's click action. |callback| is called when the menu item - // is activated. - void UpdateClickActionReplacementMenuItem(const char* label, - const base::Closure& callback); - - // Refreshes all the menu item labels and menu item checked/enabled states. - void Refresh(); - - GtkMenu* GetGtkMenu(); - - private: - // Callback for when the "click action replacement" menu item is activated. - CHROMEGTK_CALLBACK_0(AppIndicatorIconMenu, - void, - OnClickActionReplacementMenuItemActivated); - - // Callback for when a menu item is activated. - CHROMEGTK_CALLBACK_0(AppIndicatorIconMenu, void, OnMenuItemActivated); - - // Not owned. - ui::MenuModel* menu_model_; - - // Whether a "click action replacement" menu item has been added to the menu. - bool click_action_replacement_menu_item_added_; - - // Called when the click action replacement menu item is activated. When a - // menu item from |menu_model_| is activated, MenuModel::ActivatedAt() is - // invoked and is assumed to do any necessary processing. - base::Closure click_action_replacement_callback_; - - GtkWidget* gtk_menu_; - - bool block_activation_; - - DISALLOW_COPY_AND_ASSIGN(AppIndicatorIconMenu); -}; - -} // namespace libgtk2ui - -#endif // CHROME_BROWSER_UI_LIBGTK2UI_APP_INDICATOR_ICON_MENU_H_ diff --git a/chromium_src/chrome/browser/ui/libgtk2ui/gtk2_status_icon.cc b/chromium_src/chrome/browser/ui/libgtk2ui/gtk2_status_icon.cc deleted file mode 100644 index 2838bff2ea..0000000000 --- a/chromium_src/chrome/browser/ui/libgtk2ui/gtk2_status_icon.cc +++ /dev/null @@ -1,80 +0,0 @@ -// 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. - -#include "chrome/browser/ui/libgtk2ui/gtk2_status_icon.h" - -#include - -#include "base/strings/utf_string_conversions.h" -#include "chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.h" -#include "chrome/browser/ui/libgtk2ui/skia_utils_gtk2.h" -#include "ui/base/models/menu_model.h" -#include "ui/gfx/image/image_skia.h" - -namespace libgtk2ui { - -Gtk2StatusIcon::Gtk2StatusIcon(const gfx::ImageSkia& image, - const base::string16& tool_tip) { - GdkPixbuf* pixbuf = GdkPixbufFromSkBitmap(*image.bitmap()); - gtk_status_icon_ = gtk_status_icon_new_from_pixbuf(pixbuf); - g_object_unref(pixbuf); - - g_signal_connect(gtk_status_icon_, "activate", G_CALLBACK(OnClickThunk), - this); - g_signal_connect(gtk_status_icon_, "popup_menu", - G_CALLBACK(OnContextMenuRequestedThunk), this); - SetToolTip(tool_tip); -} - -Gtk2StatusIcon::~Gtk2StatusIcon() { - g_object_unref(gtk_status_icon_); -} - -void Gtk2StatusIcon::SetImage(const gfx::ImageSkia& image) { - GdkPixbuf* pixbuf = GdkPixbufFromSkBitmap(*image.bitmap()); - gtk_status_icon_set_from_pixbuf(gtk_status_icon_, pixbuf); - g_object_unref(pixbuf); -} - -void Gtk2StatusIcon::SetPressedImage(const gfx::ImageSkia& image) { - // Ignore pressed images, since the standard on Linux is to not highlight - // pressed status icons. -} - -void Gtk2StatusIcon::SetToolTip(const base::string16& tool_tip) { - gtk_status_icon_set_tooltip_text(gtk_status_icon_, - base::UTF16ToUTF8(tool_tip).c_str()); -} - -void Gtk2StatusIcon::UpdatePlatformContextMenu(ui::MenuModel* model) { - menu_.reset(); - if (model) - menu_.reset(new AppIndicatorIconMenu(model)); -} - -void Gtk2StatusIcon::RefreshPlatformContextMenu() { - if (menu_.get()) - menu_->Refresh(); -} - -void Gtk2StatusIcon::OnClick(GtkStatusIcon* status_icon) { - if (delegate()) - delegate()->OnClick(); -} - -void Gtk2StatusIcon::OnContextMenuRequested(GtkStatusIcon* status_icon, - guint button, - guint32 activate_time) { - if (menu_.get()) { - gtk_menu_popup(menu_->GetGtkMenu(), - NULL, - NULL, - gtk_status_icon_position_menu, - gtk_status_icon_, - button, - activate_time); - } -} - -} // namespace libgtk2ui diff --git a/chromium_src/chrome/browser/ui/libgtk2ui/gtk2_status_icon.h b/chromium_src/chrome/browser/ui/libgtk2ui/gtk2_status_icon.h deleted file mode 100644 index d25b487b62..0000000000 --- a/chromium_src/chrome/browser/ui/libgtk2ui/gtk2_status_icon.h +++ /dev/null @@ -1,61 +0,0 @@ -// 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. - -#ifndef CHROME_BROWSER_UI_LIBGTK2UI_GTK2_STATUS_ICON_H_ -#define CHROME_BROWSER_UI_LIBGTK2UI_GTK2_STATUS_ICON_H_ - -#include "base/memory/scoped_ptr.h" -#include "base/strings/string16.h" -#include "chrome/browser/ui/libgtk2ui/gtk2_signal.h" -#include "ui/base/glib/glib_integers.h" -#include "ui/base/glib/glib_signal.h" -#include "ui/views/linux_ui/status_icon_linux.h" - -typedef struct _GtkStatusIcon GtkStatusIcon; - -namespace gfx { -class ImageSkia; -} - -namespace ui { -class MenuModel; -} - -namespace libgtk2ui { -class AppIndicatorIconMenu; - -// Status icon implementation which uses the system tray X11 spec (via -// GtkStatusIcon). -class Gtk2StatusIcon : public views::StatusIconLinux { - public: - Gtk2StatusIcon(const gfx::ImageSkia& image, const base::string16& tool_tip); - virtual ~Gtk2StatusIcon(); - - // Overridden from views::StatusIconLinux: - virtual void SetImage(const gfx::ImageSkia& image) OVERRIDE; - virtual void SetPressedImage(const gfx::ImageSkia& image) OVERRIDE; - virtual void SetToolTip(const base::string16& tool_tip) OVERRIDE; - virtual void UpdatePlatformContextMenu(ui::MenuModel* menu) OVERRIDE; - virtual void RefreshPlatformContextMenu() OVERRIDE; - - private: - CHROMEG_CALLBACK_0(Gtk2StatusIcon, void, OnClick, GtkStatusIcon*); - - CHROMEG_CALLBACK_2(Gtk2StatusIcon, - void, - OnContextMenuRequested, - GtkStatusIcon*, - guint, - guint); - - GtkStatusIcon* gtk_status_icon_; - - scoped_ptr menu_; - - DISALLOW_COPY_AND_ASSIGN(Gtk2StatusIcon); -}; - -} // namespace libgtk2ui - -#endif // CHROME_BROWSER_UI_LIBGTK2UI_GTK2_STATUS_ICON_H_ From 1853bef39a183618ec8b96724f4bf6c3039f1c50 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 9 Dec 2014 16:52:11 -0800 Subject: [PATCH 25/41] views: SizeConstraintsChanged has become required --- atom/browser/ui/views/frameless_view.cc | 3 +++ atom/browser/ui/views/frameless_view.h | 1 + atom/browser/ui/views/win_frame_view.cc | 3 +++ atom/browser/ui/views/win_frame_view.h | 1 + 4 files changed, 8 insertions(+) diff --git a/atom/browser/ui/views/frameless_view.cc b/atom/browser/ui/views/frameless_view.cc index 7e98085e0d..03a31e0828 100644 --- a/atom/browser/ui/views/frameless_view.cc +++ b/atom/browser/ui/views/frameless_view.cc @@ -95,6 +95,9 @@ void FramelessView::UpdateWindowIcon() { void FramelessView::UpdateWindowTitle() { } +void FramelessView::SizeConstraintsChanged() { +} + gfx::Size FramelessView::GetPreferredSize() const { return frame_->non_client_view()->GetWindowBoundsForClientBounds( gfx::Rect(frame_->client_view()->GetPreferredSize())).size(); diff --git a/atom/browser/ui/views/frameless_view.h b/atom/browser/ui/views/frameless_view.h index f07a8c6758..54dc3285fa 100644 --- a/atom/browser/ui/views/frameless_view.h +++ b/atom/browser/ui/views/frameless_view.h @@ -36,6 +36,7 @@ class FramelessView : public views::NonClientFrameView { void ResetWindowControls() override; void UpdateWindowIcon() override; void UpdateWindowTitle() override; + void SizeConstraintsChanged() override; // Overridden from View: gfx::Size GetPreferredSize() const override; diff --git a/atom/browser/ui/views/win_frame_view.cc b/atom/browser/ui/views/win_frame_view.cc index e1ef9a018e..cb3df103d7 100644 --- a/atom/browser/ui/views/win_frame_view.cc +++ b/atom/browser/ui/views/win_frame_view.cc @@ -39,6 +39,9 @@ int WinFrameView::NonClientHitTest(const gfx::Point& point) { return FramelessView::NonClientHitTest(point); } +void WinFrameView::SizeConstraintsChanged() override { +} + gfx::Size WinFrameView::GetMinimumSize() const { gfx::Size size = FramelessView::GetMinimumSize(); return gfx::win::DIPToScreenSize(size); diff --git a/atom/browser/ui/views/win_frame_view.h b/atom/browser/ui/views/win_frame_view.h index 43bab2c8f4..3007d05d6f 100644 --- a/atom/browser/ui/views/win_frame_view.h +++ b/atom/browser/ui/views/win_frame_view.h @@ -18,6 +18,7 @@ class WinFrameView : public FramelessView { gfx::Rect GetWindowBoundsForClientBounds( const gfx::Rect& client_bounds) const override; int NonClientHitTest(const gfx::Point& point) override; + void SizeConstraintsChanged() override; // views::View: gfx::Size GetMinimumSize() const override; From cefc846e9e49e544d34504c3aa0231eb9b1bb9cf Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 9 Dec 2014 17:05:18 -0800 Subject: [PATCH 26/41] linux: Upgrade breakpad to fix building --- vendor/breakpad | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/breakpad b/vendor/breakpad index b07fb51bdb..1e937567e9 160000 --- a/vendor/breakpad +++ b/vendor/breakpad @@ -1 +1 @@ -Subproject commit b07fb51bdb232fee33711e3eb48cb56dd3c257e3 +Subproject commit 1e937567e92d2c3beed4556f3c68a4b0362b1e6d From 2db7c84cbc496524170b8b476c1214dc145c8109 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 9 Dec 2014 17:16:21 -0800 Subject: [PATCH 27/41] spec: Remove "restore" event test It is too slow and unstable. --- spec/api-browser-window-spec.coffee | 9 --------- 1 file changed, 9 deletions(-) diff --git a/spec/api-browser-window-spec.coffee b/spec/api-browser-window-spec.coffee index 09e0542c90..5bf3adcbe1 100644 --- a/spec/api-browser-window-spec.coffee +++ b/spec/api-browser-window-spec.coffee @@ -208,12 +208,3 @@ describe 'browser-window module', -> w.once 'minimize', -> done() w.show() w.minimize() - - describe 'restore event', -> - return if isCI and process.platform is 'linux' - it 'emits when window is restored', (done) -> - @timeout 10000 - w.once 'restore', -> done() - w.show() - w.minimize() - w.restore() From f57533fa0ee97bda5a196fb07e4e9ccbfd8aff2c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 9 Dec 2014 17:25:45 -0800 Subject: [PATCH 28/41] Add os_bsd variable for breakpad --- common.gypi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common.gypi b/common.gypi index d3835bbd89..becb453a96 100644 --- a/common.gypi +++ b/common.gypi @@ -12,6 +12,8 @@ 'msvs_express': 0, }], ], + # Required by breakpad. + 'os_bsd': 0, # Reflects node's config.gypi. 'component%': 'static_library', 'python': 'python', From 1cdbb6f18650a6c3c84df0ae8fd62694e6d08f5d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 9 Dec 2014 22:38:01 -0800 Subject: [PATCH 29/41] Upgrade brightray to fix running on Mac --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index f7f439bdd3..fc681b2568 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit f7f439bdd31c901c802108ec903a3bfc0448c3d1 +Subproject commit fc681b2568eb8b1fe22b1d0611ead326d6d6d374 From 6624fd9a1b346994b2dc7bd093383b53b613cbde Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 10 Dec 2014 10:51:34 -0800 Subject: [PATCH 30/41] Fix relative links in "src" of --- .../lib/web-view/web-view-attributes.coffee | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/atom/renderer/lib/web-view/web-view-attributes.coffee b/atom/renderer/lib/web-view/web-view-attributes.coffee index 9df67251a0..b1a9599024 100644 --- a/atom/renderer/lib/web-view/web-view-attributes.coffee +++ b/atom/renderer/lib/web-view/web-view-attributes.coffee @@ -3,6 +3,12 @@ guestViewInternal = require './guest-view-internal' webViewConstants = require './web-view-constants' remote = require 'remote' +# Helper function to resolve url set in attribute. +a = document.createElement 'a' +resolveUrl = (url) -> + a.href = url + a.href + # Attribute objects. # Default implementation of a WebView attribute. class WebViewAttribute @@ -107,6 +113,12 @@ class SrcAttribute extends WebViewAttribute super webViewConstants.ATTRIBUTE_SRC, webViewImpl @setupMutationObserver() + getValue: -> + if @webViewImpl.webviewNode.hasAttribute @name + resolveUrl @webViewImpl.webviewNode.getAttribute(@name) + else + '' + handleMutation: (oldValue, newValue) -> # Once we have navigated, we don't allow clearing the src attribute. # Once enters a navigated state, it cannot return to a @@ -158,9 +170,6 @@ class HttpReferrerAttribute extends WebViewAttribute constructor: (webViewImpl) -> super webViewConstants.ATTRIBUTE_HTTPREFERRER, webViewImpl - handleMutation: (oldValue, newValue) -> - SrcAttribute::parse.call this - # Sets up all of the webview attributes. WebViewImpl::setupWebViewAttributes = -> @attributes = {} From 64edede20dfa3a14624aaff3978ed37cdfc20406 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 10 Dec 2014 11:05:51 -0800 Subject: [PATCH 31/41] Move handling of "preload" to web-view-attributes --- .../lib/web-view/web-view-attributes.coffee | 15 +++++++++++++++ atom/renderer/lib/web-view/web-view.coffee | 11 ----------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/atom/renderer/lib/web-view/web-view-attributes.coffee b/atom/renderer/lib/web-view/web-view-attributes.coffee index b1a9599024..a3e97b5be4 100644 --- a/atom/renderer/lib/web-view/web-view-attributes.coffee +++ b/atom/renderer/lib/web-view/web-view-attributes.coffee @@ -170,6 +170,20 @@ class HttpReferrerAttribute extends WebViewAttribute constructor: (webViewImpl) -> super webViewConstants.ATTRIBUTE_HTTPREFERRER, webViewImpl +# Attribute that set preload script. +class PreloadAttribute extends WebViewAttribute + constructor: (webViewImpl) -> + super webViewConstants.ATTRIBUTE_PRELOAD, webViewImpl + + getValue: -> + return '' unless @webViewImpl.webviewNode.hasAttribute @name + preload = resolveUrl @webViewImpl.webviewNode.getAttribute(@name) + protocol = preload.substr 0, 5 + unless protocol in ['file:', 'asar:'] + console.error webViewConstants.ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE + preload = '' + preload + # Sets up all of the webview attributes. WebViewImpl::setupWebViewAttributes = -> @attributes = {} @@ -181,6 +195,7 @@ WebViewImpl::setupWebViewAttributes = -> @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER] = new HttpReferrerAttribute(this) @attributes[webViewConstants.ATTRIBUTE_NODEINTEGRATION] = new BooleanAttribute(webViewConstants.ATTRIBUTE_NODEINTEGRATION, this) @attributes[webViewConstants.ATTRIBUTE_PLUGINS] = new BooleanAttribute(webViewConstants.ATTRIBUTE_PLUGINS, this) + @attributes[webViewConstants.ATTRIBUTE_PRELOAD] = new PreloadAttribute(this) autosizeAttributes = [ webViewConstants.ATTRIBUTE_MAXHEIGHT diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index 89a0d4488d..c30d04e739 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -182,17 +182,6 @@ class WebViewImpl userAgentOverride: @userAgentOverride for attributeName, attribute of @attributes params[attributeName] = attribute.getValue() - if @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_PRELOAD - preload = @webviewNode.getAttribute webViewConstants.ATTRIBUTE_PRELOAD - # Get the full path. - a = document.createElement 'a' - a.href = preload - params.preload = a.href - # Only support file: or asar: protocol. - protocol = params.preload.substr 0, 5 - unless protocol in ['file:', 'asar:'] - delete params.preload - console.error webViewConstants.ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE params attachWindow: (guestInstanceId) -> From 409f2b4d0fa5a053c50855875e7d72d51ee623ec Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 10 Dec 2014 14:17:07 -0800 Subject: [PATCH 32/41] win: Fix compilation errors --- atom.gyp | 4 +- atom/app/atom_main_delegate.cc | 2 +- atom/browser/ui/views/win_frame_view.cc | 3 - atom/browser/ui/views/win_frame_view.h | 1 - .../printing/print_web_view_helper_pdf_win.cc | 250 ++++++++++++++++++ .../printing/print_web_view_helper_win.cc | 193 -------------- script/create-dist.py | 2 +- vendor/brightray | 2 +- 8 files changed, 255 insertions(+), 202 deletions(-) create mode 100644 chromium_src/chrome/renderer/printing/print_web_view_helper_pdf_win.cc delete mode 100644 chromium_src/chrome/renderer/printing/print_web_view_helper_win.cc diff --git a/atom.gyp b/atom.gyp index d835437c87..28975eb231 100644 --- a/atom.gyp +++ b/atom.gyp @@ -319,7 +319,7 @@ 'chromium_src/chrome/renderer/printing/print_web_view_helper.cc', 'chromium_src/chrome/renderer/printing/print_web_view_helper_linux.cc', 'chromium_src/chrome/renderer/printing/print_web_view_helper_mac.mm', - 'chromium_src/chrome/renderer/printing/print_web_view_helper_win.cc', + 'chromium_src/chrome/renderer/printing/print_web_view_helper_pdf_win.cc', 'chromium_src/chrome/renderer/printing/print_web_view_helper.h', 'chromium_src/chrome/renderer/tts_dispatcher.cc', 'chromium_src/chrome/renderer/tts_dispatcher.h', @@ -476,9 +476,9 @@ '<(libchromiumcontent_library_dir)/libEGL.dll', '<(libchromiumcontent_library_dir)/libGLESv2.dll', '<(libchromiumcontent_resources_dir)/icudtl.dat', + '<(libchromiumcontent_resources_dir)/content_resources_200_percent.pak', '<(libchromiumcontent_resources_dir)/content_shell.pak', '<(libchromiumcontent_resources_dir)/ui_resources_200_percent.pak', - '<(libchromiumcontent_resources_dir)/webkit_resources_200_percent.pak', 'external_binaries/d3dcompiler_43.dll', 'external_binaries/msvcp120.dll', 'external_binaries/msvcr120.dll', diff --git a/atom/app/atom_main_delegate.cc b/atom/app/atom_main_delegate.cc index 1030bb85c4..f376df8668 100644 --- a/atom/app/atom_main_delegate.cc +++ b/atom/app/atom_main_delegate.cc @@ -111,7 +111,7 @@ void AtomMainDelegate::AddDataPackFromPath( pak_dir.Append(FILE_PATH_LITERAL("ui_resources_200_percent.pak")), ui::SCALE_FACTOR_200P); bundle->AddDataPackFromPath( - pak_dir.Append(FILE_PATH_LITERAL("webkit_resources_200_percent.pak")), + pak_dir.Append(FILE_PATH_LITERAL("content_resources_200_percent.pak")), ui::SCALE_FACTOR_200P); #endif } diff --git a/atom/browser/ui/views/win_frame_view.cc b/atom/browser/ui/views/win_frame_view.cc index cb3df103d7..e1ef9a018e 100644 --- a/atom/browser/ui/views/win_frame_view.cc +++ b/atom/browser/ui/views/win_frame_view.cc @@ -39,9 +39,6 @@ int WinFrameView::NonClientHitTest(const gfx::Point& point) { return FramelessView::NonClientHitTest(point); } -void WinFrameView::SizeConstraintsChanged() override { -} - gfx::Size WinFrameView::GetMinimumSize() const { gfx::Size size = FramelessView::GetMinimumSize(); return gfx::win::DIPToScreenSize(size); diff --git a/atom/browser/ui/views/win_frame_view.h b/atom/browser/ui/views/win_frame_view.h index 3007d05d6f..43bab2c8f4 100644 --- a/atom/browser/ui/views/win_frame_view.h +++ b/atom/browser/ui/views/win_frame_view.h @@ -18,7 +18,6 @@ class WinFrameView : public FramelessView { gfx::Rect GetWindowBoundsForClientBounds( const gfx::Rect& client_bounds) const override; int NonClientHitTest(const gfx::Point& point) override; - void SizeConstraintsChanged() override; // views::View: gfx::Size GetMinimumSize() const override; diff --git a/chromium_src/chrome/renderer/printing/print_web_view_helper_pdf_win.cc b/chromium_src/chrome/renderer/printing/print_web_view_helper_pdf_win.cc new file mode 100644 index 0000000000..21e0c26e28 --- /dev/null +++ b/chromium_src/chrome/renderer/printing/print_web_view_helper_pdf_win.cc @@ -0,0 +1,250 @@ +// 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. + +#include "chrome/renderer/printing/print_web_view_helper.h" + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/process/process_handle.h" +#include "chrome/common/print_messages.h" +#include "content/public/renderer/render_thread.h" +#include "printing/metafile_skia_wrapper.h" +#include "printing/page_size_margins.h" +#include "printing/pdf_metafile_skia.h" +#include "printing/units.h" +#include "skia/ext/platform_device.h" +#include "skia/ext/vector_canvas.h" +#include "third_party/WebKit/public/web/WebLocalFrame.h" + + +namespace printing { + +using blink::WebFrame; + +#if 0 +bool PrintWebViewHelper::RenderPreviewPage( + int page_number, + const PrintMsg_Print_Params& print_params) { + PrintMsg_PrintPage_Params page_params; + page_params.params = print_params; + page_params.page_number = page_number; + scoped_ptr draft_metafile; + PdfMetafileSkia* initial_render_metafile = print_preview_context_.metafile(); + if (print_preview_context_.IsModifiable() && is_print_ready_metafile_sent_) { + draft_metafile.reset(new PdfMetafileSkia); + initial_render_metafile = draft_metafile.get(); + } + + base::TimeTicks begin_time = base::TimeTicks::Now(); + PrintPageInternal(page_params, + print_preview_context_.prepared_frame(), + initial_render_metafile, + NULL, + NULL); + print_preview_context_.RenderedPreviewPage( + base::TimeTicks::Now() - begin_time); + if (draft_metafile.get()) { + draft_metafile->FinishDocument(); + } else if (print_preview_context_.IsModifiable() && + print_preview_context_.generate_draft_pages()) { + DCHECK(!draft_metafile.get()); + draft_metafile = + print_preview_context_.metafile()->GetMetafileForCurrentPage(); + } + return PreviewPageRendered(page_number, draft_metafile.get()); +} +#endif + +bool PrintWebViewHelper::PrintPagesNative(blink::WebFrame* frame, + int page_count) { + PdfMetafileSkia metafile; + if (!metafile.Init()) + return false; + + const PrintMsg_PrintPages_Params& params = *print_pages_params_; + std::vector printed_pages; + if (params.pages.empty()) { + for (int i = 0; i < page_count; ++i) { + printed_pages.push_back(i); + } + } else { + // TODO(vitalybuka): redesign to make more code cross platform. + for (size_t i = 0; i < params.pages.size(); ++i) { + if (params.pages[i] >= 0 && params.pages[i] < page_count) { + printed_pages.push_back(params.pages[i]); + } + } + } + if (printed_pages.empty()) + return false; + + std::vector page_size_in_dpi(printed_pages.size()); + std::vector content_area_in_dpi(printed_pages.size()); + + PrintMsg_PrintPage_Params page_params; + page_params.params = params.params; + for (size_t i = 0; i < printed_pages.size(); ++i) { + page_params.page_number = printed_pages[i]; + PrintPageInternal(page_params, + frame, + &metafile, + &page_size_in_dpi[i], + &content_area_in_dpi[i]); + } + + // blink::printEnd() for PDF should be called before metafile is closed. + FinishFramePrinting(); + + metafile.FinishDocument(); + + // Get the size of the resulting metafile. + uint32 buf_size = metafile.GetDataSize(); + DCHECK_GT(buf_size, 0u); + + PrintHostMsg_DidPrintPage_Params printed_page_params; + printed_page_params.data_size = 0; + printed_page_params.document_cookie = params.params.document_cookie; + printed_page_params.page_size = params.params.page_size; + printed_page_params.content_area = params.params.printable_area; + + { + base::SharedMemory shared_buf; + // Allocate a shared memory buffer to hold the generated metafile data. + if (!shared_buf.CreateAndMapAnonymous(buf_size)) { + NOTREACHED() << "Buffer allocation failed"; + return false; + } + + // Copy the bits into shared memory. + if (!metafile.GetData(shared_buf.memory(), buf_size)) { + NOTREACHED() << "GetData() failed"; + shared_buf.Unmap(); + return false; + } + shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), + &printed_page_params.metafile_data_handle); + shared_buf.Unmap(); + + printed_page_params.data_size = buf_size; + Send(new PrintHostMsg_DuplicateSection( + routing_id(), + printed_page_params.metafile_data_handle, + &printed_page_params.metafile_data_handle)); + } + + for (size_t i = 0; i < printed_pages.size(); ++i) { + printed_page_params.page_number = printed_pages[i]; + printed_page_params.page_size = page_size_in_dpi[i]; + printed_page_params.content_area = content_area_in_dpi[i]; + Send(new PrintHostMsg_DidPrintPage(routing_id(), printed_page_params)); + printed_page_params.metafile_data_handle = INVALID_HANDLE_VALUE; + } + return true; +} + +void PrintWebViewHelper::PrintPageInternal( + const PrintMsg_PrintPage_Params& params, + WebFrame* frame, + PdfMetafileSkia* metafile, + gfx::Size* page_size_in_dpi, + gfx::Rect* content_area_in_dpi) { + PageSizeMargins page_layout_in_points; + double css_scale_factor = 1.0f; + ComputePageLayoutInPointsForCss(frame, params.page_number, params.params, + ignore_css_margins_, &css_scale_factor, + &page_layout_in_points); + gfx::Size page_size; + gfx::Rect content_area; + GetPageSizeAndContentAreaFromPageLayout(page_layout_in_points, &page_size, + &content_area); + int dpi = static_cast(params.params.dpi); + // Calculate the actual page size and content area in dpi. + if (page_size_in_dpi) { + *page_size_in_dpi = + gfx::Size(static_cast(ConvertUnitDouble( + page_size.width(), kPointsPerInch, dpi)), + static_cast(ConvertUnitDouble( + page_size.height(), kPointsPerInch, dpi))); + } + + if (content_area_in_dpi) { + // Output PDF matches paper size and should be printer edge to edge. + *content_area_in_dpi = + gfx::Rect(0, 0, page_size_in_dpi->width(), page_size_in_dpi->height()); + } + + gfx::Rect canvas_area = + content_area; +#if 0 + params.params.display_header_footer ? gfx::Rect(page_size) : content_area; +#endif + + float webkit_page_shrink_factor = + frame->getPrintPageShrink(params.page_number); + float scale_factor = css_scale_factor * webkit_page_shrink_factor; + + SkBaseDevice* device = metafile->StartPageForVectorCanvas(page_size, + canvas_area, + scale_factor); + if (!device) + return; + + // The printPage method take a reference to the canvas we pass down, so it + // can't be a stack object. + skia::RefPtr canvas = + skia::AdoptRef(new skia::VectorCanvas(device)); + MetafileSkiaWrapper::SetMetafileOnCanvas(*canvas, metafile); + skia::SetIsDraftMode(*canvas, is_print_ready_metafile_sent_); + +#if 0 + if (params.params.display_header_footer) { + // |page_number| is 0-based, so 1 is added. + PrintHeaderAndFooter(canvas.get(), + params.page_number + 1, + print_preview_context_.total_page_count(), + *frame, + scale_factor, + page_layout_in_points, + params.params); + } +#endif + + float webkit_scale_factor = RenderPageContent(frame, + params.page_number, + canvas_area, + content_area, + scale_factor, + canvas.get()); + DCHECK_GT(webkit_scale_factor, 0.0f); + // Done printing. Close the device context to retrieve the compiled metafile. + if (!metafile->FinishPage()) + NOTREACHED() << "metafile failed"; +} + +bool PrintWebViewHelper::CopyMetafileDataToSharedMem( + PdfMetafileSkia* metafile, + base::SharedMemoryHandle* shared_mem_handle) { + uint32 buf_size = metafile->GetDataSize(); + base::SharedMemory shared_buf; + // Allocate a shared memory buffer to hold the generated metafile data. + if (!shared_buf.CreateAndMapAnonymous(buf_size)) { + NOTREACHED() << "Buffer allocation failed"; + return false; + } + + // Copy the bits into shared memory. + if (!metafile->GetData(shared_buf.memory(), buf_size)) { + NOTREACHED() << "GetData() failed"; + shared_buf.Unmap(); + return false; + } + shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), shared_mem_handle); + shared_buf.Unmap(); + + Send(new PrintHostMsg_DuplicateSection(routing_id(), *shared_mem_handle, + shared_mem_handle)); + return true; +} + +} // namespace printing diff --git a/chromium_src/chrome/renderer/printing/print_web_view_helper_win.cc b/chromium_src/chrome/renderer/printing/print_web_view_helper_win.cc deleted file mode 100644 index 4c1a78332c..0000000000 --- a/chromium_src/chrome/renderer/printing/print_web_view_helper_win.cc +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/renderer/printing/print_web_view_helper.h" - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/metrics/histogram.h" -#include "base/process/process_handle.h" -#include "base/win/scoped_gdi_object.h" -#include "base/win/scoped_hdc.h" -#include "base/win/scoped_select_object.h" -#include "chrome/common/print_messages.h" -#include "printing/metafile.h" -#include "printing/metafile_impl.h" -#include "printing/metafile_skia_wrapper.h" -#include "printing/page_size_margins.h" -#include "printing/units.h" -#include "skia/ext/platform_device.h" -#include "skia/ext/refptr.h" -#include "skia/ext/vector_canvas.h" -#include "third_party/WebKit/public/web/WebLocalFrame.h" -#include "ui/gfx/gdi_util.h" -#include "ui/gfx/point.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/size.h" - -namespace printing { - -using blink::WebFrame; - -void PrintWebViewHelper::PrintPageInternal( - const PrintMsg_PrintPage_Params& params, - const gfx::Size& canvas_size, - WebFrame* frame) { - // Generate a memory-based metafile. It will use the current screen's DPI. - // Each metafile contains a single page. - scoped_ptr metafile(new NativeMetafile); - metafile->Init(); - DCHECK(metafile->context()); - skia::InitializeDC(metafile->context()); - - int page_number = params.page_number; - - // Calculate the dpi adjustment. - // Browser will render context using desired_dpi, so we need to calculate - // adjustment factor to play content on the printer DC later during the - // actual printing. - double actual_shrink = static_cast(params.params.desired_dpi / - params.params.dpi); - gfx::Size page_size_in_dpi; - gfx::Rect content_area_in_dpi; - - // Render page for printing. - RenderPage(params.params, page_number, frame, false, metafile.get(), - &actual_shrink, &page_size_in_dpi, &content_area_in_dpi); - - // Close the device context to retrieve the compiled metafile. - if (!metafile->FinishDocument()) - NOTREACHED(); - - if (!params.params.supports_alpha_blend && metafile->IsAlphaBlendUsed()) { - scoped_ptr raster_metafile( - metafile->RasterizeAlphaBlend()); - if (raster_metafile.get()) - metafile.swap(raster_metafile); - } - - // Get the size of the compiled metafile. - uint32 buf_size = metafile->GetDataSize(); - DCHECK_GT(buf_size, 128u); - - PrintHostMsg_DidPrintPage_Params page_params; - page_params.data_size = buf_size; - page_params.metafile_data_handle = NULL; - page_params.page_number = page_number; - page_params.document_cookie = params.params.document_cookie; - page_params.actual_shrink = actual_shrink; - page_params.page_size = page_size_in_dpi; - page_params.content_area = content_area_in_dpi; - - if (!CopyMetafileDataToSharedMem(metafile.get(), - &(page_params.metafile_data_handle))) { - page_params.data_size = 0; - } - - Send(new PrintHostMsg_DidPrintPage(routing_id(), page_params)); -} - -void PrintWebViewHelper::RenderPage( - const PrintMsg_Print_Params& params, int page_number, WebFrame* frame, - bool is_preview, Metafile* metafile, double* actual_shrink, - gfx::Size* page_size_in_dpi, gfx::Rect* content_area_in_dpi) { - PageSizeMargins page_layout_in_points; - double css_scale_factor = 1.0f; - ComputePageLayoutInPointsForCss(frame, page_number, params, - ignore_css_margins_, &css_scale_factor, - &page_layout_in_points); - gfx::Size page_size; - gfx::Rect content_area; - GetPageSizeAndContentAreaFromPageLayout(page_layout_in_points, &page_size, - &content_area); - int dpi = static_cast(params.dpi); - // Calculate the actual page size and content area in dpi. - if (page_size_in_dpi) { - *page_size_in_dpi = gfx::Size( - static_cast(ConvertUnitDouble(page_size.width(), kPointsPerInch, - dpi)), - static_cast(ConvertUnitDouble(page_size.height(), kPointsPerInch, - dpi))); - } - - if (content_area_in_dpi) { - *content_area_in_dpi = gfx::Rect( - static_cast(ConvertUnitDouble(content_area.x(), kPointsPerInch, - dpi)), - static_cast(ConvertUnitDouble(content_area.y(), kPointsPerInch, - dpi)), - static_cast(ConvertUnitDouble(content_area.width(), kPointsPerInch, - dpi)), - static_cast(ConvertUnitDouble(content_area.height(), - kPointsPerInch, dpi))); - } - - float webkit_page_shrink_factor = frame->getPrintPageShrink(page_number); - float scale_factor = css_scale_factor * webkit_page_shrink_factor; - - gfx::Rect canvas_area = content_area; - - SkBaseDevice* device = metafile->StartPageForVectorCanvas( - page_size, canvas_area, scale_factor); - DCHECK(device); - // The printPage method may take a reference to the canvas we pass down, so it - // can't be a stack object. - skia::RefPtr canvas = - skia::AdoptRef(new skia::VectorCanvas(device)); - - float webkit_scale_factor = RenderPageContent(frame, page_number, canvas_area, - content_area, scale_factor, - canvas.get()); - - if (*actual_shrink <= 0 || webkit_scale_factor <= 0) { - NOTREACHED() << "Printing page " << page_number << " failed."; - } else { - // While rendering certain plugins (PDF) to metafile, we might need to - // set custom scale factor. Update |actual_shrink| with custom scale - // if it is set on canvas. - // TODO(gene): We should revisit this solution for the next versions. - // Consider creating metafile of the right size (or resizable) - // https://code.google.com/p/chromium/issues/detail?id=126037 - if (!MetafileSkiaWrapper::GetCustomScaleOnCanvas( - *canvas, actual_shrink)) { - // Update the dpi adjustment with the "page |actual_shrink|" calculated in - // webkit. - *actual_shrink /= (webkit_scale_factor * css_scale_factor); - } - } - - bool result = metafile->FinishPage(); - DCHECK(result); -} - -bool PrintWebViewHelper::CopyMetafileDataToSharedMem( - Metafile* metafile, base::SharedMemoryHandle* shared_mem_handle) { - uint32 buf_size = metafile->GetDataSize(); - base::SharedMemory shared_buf; - if (buf_size >= kMetafileMaxSize) { - NOTREACHED() << "Buffer too large: " << buf_size; - return false; - } - - // Allocate a shared memory buffer to hold the generated metafile data. - if (!shared_buf.CreateAndMapAnonymous(buf_size)) { - NOTREACHED() << "Buffer allocation failed"; - return false; - } - - // Copy the bits into shared memory. - if (!metafile->GetData(shared_buf.memory(), buf_size)) { - NOTREACHED() << "GetData() failed"; - shared_buf.Unmap(); - return false; - } - shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), shared_mem_handle); - shared_buf.Unmap(); - - Send(new PrintHostMsg_DuplicateSection(routing_id(), *shared_mem_handle, - shared_mem_handle)); - return true; -} - -} // namespace printing diff --git a/script/create-dist.py b/script/create-dist.py index e623b088c6..2eeed1e55a 100755 --- a/script/create-dist.py +++ b/script/create-dist.py @@ -43,9 +43,9 @@ TARGET_BINARIES = { 'libGLESv2.dll', 'msvcp120.dll', 'msvcr120.dll', + 'content_resources_200_percent.pak', 'ui_resources_200_percent.pak', 'vccorlib120.dll', - 'webkit_resources_200_percent.pak', 'xinput1_3.dll', ], 'linux': [ diff --git a/vendor/brightray b/vendor/brightray index fc681b2568..d70727848e 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit fc681b2568eb8b1fe22b1d0611ead326d6d6d374 +Subproject commit d70727848e4658ced013aee69dc073a8fcccfcaa From 0b668b8e175e5e48db6fe5eb7d6e763495bed5f9 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 11 Dec 2014 09:07:50 -0800 Subject: [PATCH 33/41] Minor fixes on --- atom/renderer/lib/web-view/guest-view-internal.coffee | 3 ++- atom/renderer/lib/web-view/web-view.coffee | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/atom/renderer/lib/web-view/guest-view-internal.coffee b/atom/renderer/lib/web-view/guest-view-internal.coffee index 96a8c6edea..5757536ac4 100644 --- a/atom/renderer/lib/web-view/guest-view-internal.coffee +++ b/atom/renderer/lib/web-view/guest-view-internal.coffee @@ -40,7 +40,8 @@ module.exports = ipc.once "ATOM_SHELL_RESPONSE_#{requestId}", callback attachGuest: (elementInstanceId, guestInstanceId, params, callback) -> - ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', elementInstanceId, guestInstanceId, params + requestId++ + ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', elementInstanceId, guestInstanceId, params, requestId ipc.once "ATOM_SHELL_RESPONSE_#{requestId}", callback webFrame.attachGuest elementInstanceId diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index c30d04e739..e095c0b74d 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -105,7 +105,7 @@ class WebViewImpl return unless @guestInstanceId - guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, params, (w) => @contentWindow = w + guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, @buildAttachParams(), (w) => @contentWindow = w onSizeChanged: (webViewEvent) -> newWidth = webViewEvent.newWidth From 7457f8128345d5ff16c582bf4d141574809f90fc Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 11 Dec 2014 14:25:51 -0800 Subject: [PATCH 34/41] mac: Fix installing view on frameless window Closes #601. --- atom/browser/native_window_mac.h | 4 +++ atom/browser/native_window_mac.mm | 46 +++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index 3170239ed8..2a34fe4151 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -11,6 +11,7 @@ #include "base/memory/scoped_ptr.h" #include "atom/browser/native_window.h" +@class FullSizeContentView; class SkRegion; namespace atom { @@ -98,6 +99,9 @@ class NativeWindowMac : public NativeWindow { base::scoped_nsobject window_; + // The view that will fill the whole frameless window. + base::scoped_nsobject content_view_; + bool is_kiosk_; NSInteger attention_request_id_; // identifier from requestUserAttention diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 131e2096d4..17e361f789 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -25,6 +25,31 @@ static const CGFloat kAtomWindowCornerRadius = 4.0; - (CGFloat)roundedCornerRadius; @end +// This view always takes the size of its superview. It is intended to be used +// as a NSWindow's contentView. It is needed because NSWindow's implementation +// explicitly resizes the contentView at inopportune times. +@interface FullSizeContentView : NSView +@end + +@implementation FullSizeContentView + +// This method is directly called by NSWindow during a window resize on OSX +// 10.10.0, beta 2. We must override it to prevent the content view from +// shrinking. +- (void)setFrameSize:(NSSize)size { + if ([self superview]) + size = [[self superview] bounds].size; + [super setFrameSize:size]; +} + +// The contentView gets moved around during certain full-screen operations. +// This is less than ideal, and should eventually be removed. +- (void)viewDidMoveToSuperview { + [self setFrame:[[self superview] bounds]]; +} + +@end + @interface AtomNSWindowDelegate : NSObject { @private atom::NativeWindowMac* shell_; @@ -690,9 +715,24 @@ void NativeWindowMac::InstallView() { [view setFrame:[[window_ contentView] bounds]]; [[window_ contentView] addSubview:view]; } else { - NSView* frameView = [[window_ contentView] superview]; - [view setFrame:[frameView bounds]]; - [frameView addSubview:view]; + if (base::mac::IsOSYosemiteOrLater()) { + // In OSX 10.10, adding subviews to the root view for the NSView hierarchy + // produces warnings. To eliminate the warnings, we resize the contentView + // to fill the window, and add subviews to that. + // http://crbug.com/380412 + content_view_.reset([[FullSizeContentView alloc] init]); + [content_view_ + setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + [content_view_ setFrame:[[[window_ contentView] superview] bounds]]; + [window_ setContentView:content_view_]; + + [view setFrame:[content_view_ bounds]]; + [content_view_ addSubview:view]; + } else { + NSView* frameView = [[window_ contentView] superview]; + [view setFrame:[frameView bounds]]; + [frameView addSubview:view]; + } ClipWebView(); From d8d9dea792a8be183159014fe7ec66505dad9cbf Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 11 Dec 2014 18:33:39 -0800 Subject: [PATCH 35/41] Upgrade node to fix failed call to LoadLibrary --- script/bootstrap.py | 8 ++++---- vendor/node | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/script/bootstrap.py b/script/bootstrap.py index 5f288dce1c..c2554e213a 100755 --- a/script/bootstrap.py +++ b/script/bootstrap.py @@ -21,18 +21,18 @@ def main(): args = parse_args() if args.verbose: enable_verbose_mode() - update_submodules() - update_node_modules('.') - update_atom_modules('spec') - bootstrap_brightray(args.url) if sys.platform == 'cygwin': update_win32_python() + update_submodules() + update_node_modules('.') + bootstrap_brightray(args.url) if sys.platform in ['win32', 'cygwin']: install_runas() create_chrome_version_h() touch_config_gypi() update_atom_shell() + update_atom_modules('spec') def parse_args(): diff --git a/vendor/node b/vendor/node index c8a1feaf57..296b2c198b 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit c8a1feaf57cf32a893395b255df7a8471e42a822 +Subproject commit 296b2c198be867ed89144acb20bd3570ce375cf5 From 1bebf1cc2c68b67798f298a5c79d2ae771f44e1e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 11 Dec 2014 19:29:36 -0800 Subject: [PATCH 36/41] win: Fix generating location.pak. --- atom.gyp | 5 +++-- tools/make_locale_paks.py | 35 +++++++++++++++++++++++++++++++++ tools/posix/make_locale_paks.sh | 33 ------------------------------- 3 files changed, 38 insertions(+), 35 deletions(-) create mode 100755 tools/make_locale_paks.py delete mode 100755 tools/posix/make_locale_paks.sh diff --git a/atom.gyp b/atom.gyp index 28975eb231..249185a321 100644 --- a/atom.gyp +++ b/atom.gyp @@ -883,13 +883,14 @@ { 'action_name': 'Make Empty Paks', 'inputs': [ - 'tools/posix/make_locale_paks.sh', + 'tools/make_locale_paks.py', ], 'outputs': [ '<(PRODUCT_DIR)/locales' ], 'action': [ - 'tools/posix/make_locale_paks.sh', + 'python', + 'tools/make_locale_paks.py', '<(PRODUCT_DIR)', '<@(locales)', ], diff --git a/tools/make_locale_paks.py b/tools/make_locale_paks.py new file mode 100755 index 0000000000..70597f54ab --- /dev/null +++ b/tools/make_locale_paks.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python + +# usage: make_locale_paks build_dir [...] +# +# This script creates the .pak files under locales directory, it is used to fool +# the ResourcesBundle that the locale is available. + +import errno +import sys +import os + + +def main(): + target_dir = sys.argv[1] + locale_dir = os.path.join(target_dir, 'locales') + safe_mkdir(locale_dir) + for pak in sys.argv[2:]: + touch(os.path.join(locale_dir, pak + '.pak')) + + +def touch(filename): + with open(filename, 'w+'): + pass + + +def safe_mkdir(path): + try: + os.makedirs(path) + except OSError as e: + if e.errno != errno.EEXIST: + raise + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/tools/posix/make_locale_paks.sh b/tools/posix/make_locale_paks.sh deleted file mode 100755 index 6f66a04e86..0000000000 --- a/tools/posix/make_locale_paks.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2011 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# usage: make_locale_paks locale_dir [...] -# -# This script creates the .pak files under locales directory, it is used to fool -# the ResourcesBundle that the locale is available. - -set -eu - -if [[ ${#} -eq 0 ]]; then - echo "usage: ${0} build_dir [locale_pak...]" >& 2 - exit 1 -fi - -PRODUCT_DIR="$1" -shift - -LOCALES_DIR="${PRODUCT_DIR}/locales" -if [[ ! -d "${LOCALES_DIR}" ]]; then - mkdir "${LOCALES_DIR}" -fi - -cd "${LOCALES_DIR}" - -for pak in "${@}"; do - if [[ ! -f "${pak}.pak" ]]; then - touch "${pak}.pak" - fi -done From 290dd4ccd825c037f2654991692d94d2f70c13e9 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 11 Dec 2014 19:45:28 -0800 Subject: [PATCH 37/41] win: Use d3dcompiler_46.dll --- atom.gyp | 2 +- script/create-dist.py | 2 +- script/update-external-binaries.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/atom.gyp b/atom.gyp index 249185a321..9bb06cf002 100644 --- a/atom.gyp +++ b/atom.gyp @@ -479,7 +479,7 @@ '<(libchromiumcontent_resources_dir)/content_resources_200_percent.pak', '<(libchromiumcontent_resources_dir)/content_shell.pak', '<(libchromiumcontent_resources_dir)/ui_resources_200_percent.pak', - 'external_binaries/d3dcompiler_43.dll', + 'external_binaries/d3dcompiler_46.dll', 'external_binaries/msvcp120.dll', 'external_binaries/msvcr120.dll', 'external_binaries/vccorlib120.dll', diff --git a/script/create-dist.py b/script/create-dist.py index 2eeed1e55a..8a83c954e7 100755 --- a/script/create-dist.py +++ b/script/create-dist.py @@ -36,7 +36,7 @@ TARGET_BINARIES = { 'atom.exe', 'chromiumcontent.dll', 'content_shell.pak', - 'd3dcompiler_43.dll', + 'd3dcompiler_46.dll', 'ffmpegsumo.dll', 'icudtl.dat', 'libEGL.dll', diff --git a/script/update-external-binaries.py b/script/update-external-binaries.py index 5bb980118d..7e134238fc 100755 --- a/script/update-external-binaries.py +++ b/script/update-external-binaries.py @@ -7,7 +7,7 @@ import os from lib.util import safe_mkdir, rm_rf, extract_zip, tempdir, download -VERSION = 'v0.2.0' +VERSION = 'v0.3.0' SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) FRAMEWORKS_URL = 'https://github.com/atom/atom-shell-frameworks/releases' \ '/download/' + VERSION From e38614ce315f627d41a2d2d2acb6ea5c3be65765 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 11 Dec 2014 19:47:15 -0800 Subject: [PATCH 38/41] win: No longer support building with VS Express The Community edition can provide everything we need for Professional edition. --- atom.gyp | 26 -------------------------- common.gypi | 5 ----- script/update-external-binaries.py | 1 - 3 files changed, 32 deletions(-) diff --git a/atom.gyp b/atom.gyp index 9bb06cf002..b4cd71c439 100644 --- a/atom.gyp +++ b/atom.gyp @@ -932,31 +932,5 @@ }, # target generate_node_lib ], }], # OS==win - # Using Visual Studio Express. - ['msvs_express==1', { - 'target_defaults': { - 'defines!': [ - '_SECURE_ATL', - ], - 'msvs_settings': { - 'VCLibrarianTool': { - 'AdditionalLibraryDirectories': [ - '<(atom_source_root)/external_binaries/atl/lib', - ], - }, - 'VCLinkerTool': { - 'AdditionalLibraryDirectories': [ - '<(atom_source_root)/external_binaries/atl/lib', - ], - 'AdditionalDependencies': [ - 'atls.lib', - ], - }, - }, - 'msvs_system_include_dirs': [ - '<(atom_source_root)/external_binaries/atl/include', - ], - }, - }], # msvs_express==1 ], } diff --git a/common.gypi b/common.gypi index becb453a96..7ee6d494a4 100644 --- a/common.gypi +++ b/common.gypi @@ -6,11 +6,6 @@ ['OS=="mac" or OS=="linux"', { 'clang': 1, }], - ['OS=="win" and (MSVS_VERSION=="2013e" or MSVS_VERSION=="2012e" or MSVS_VERSION=="2010e")', { - 'msvs_express': 1, - },{ - 'msvs_express': 0, - }], ], # Required by breakpad. 'os_bsd': 0, diff --git a/script/update-external-binaries.py b/script/update-external-binaries.py index 7e134238fc..80f0df5717 100755 --- a/script/update-external-binaries.py +++ b/script/update-external-binaries.py @@ -28,7 +28,6 @@ def main(): download_and_unzip('ReactiveCocoa') download_and_unzip('Squirrel') elif sys.platform in ['cygwin', 'win32']: - download_and_unzip('atl') download_and_unzip('directxsdk') download_and_unzip('vs2012_crt') From e3ccb18696c3ddfc9dadd5dc4593bd9f5f88023b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 12 Dec 2014 09:04:43 -0800 Subject: [PATCH 39/41] win: Fix calculating window bounds on high DPI display --- atom/browser/native_window_views.cc | 8 ++++++++ atom/browser/ui/views/win_frame_view.cc | 14 +++----------- atom/browser/ui/views/win_frame_view.h | 2 -- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 9ee492aaa6..8825371dc3 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -49,6 +49,7 @@ #include "base/win/scoped_comptr.h" #include "base/win/windows_version.h" #include "ui/base/win/shell.h" +#include "ui/gfx/win/dpi.h" #include "ui/views/win/hwnd_util.h" #endif @@ -837,8 +838,15 @@ void NativeWindowViews::RegisterAccelerators(ui::MenuModel* menu_model) { gfx::Rect NativeWindowViews::ContentBoundsToWindowBounds( const gfx::Rect& bounds) { +#if defined(OS_WIN) + gfx::Rect dpi_bounds = gfx::win::DIPToScreenRect(bounds); + gfx::Rect window_bounds = gfx::win::ScreenToDIPRect( + window_->non_client_view()->GetWindowBoundsForClientBounds(dpi_bounds)); +#else gfx::Rect window_bounds = window_->non_client_view()->GetWindowBoundsForClientBounds(bounds); +#endif + if (menu_bar_ && menu_bar_visible_) window_bounds.set_height(window_bounds.height() + kMenuBarHeight); return window_bounds; diff --git a/atom/browser/ui/views/win_frame_view.cc b/atom/browser/ui/views/win_frame_view.cc index e1ef9a018e..db74661932 100644 --- a/atom/browser/ui/views/win_frame_view.cc +++ b/atom/browser/ui/views/win_frame_view.cc @@ -27,9 +27,9 @@ WinFrameView::~WinFrameView() { gfx::Rect WinFrameView::GetWindowBoundsForClientBounds( const gfx::Rect& client_bounds) const { - gfx::Size size(client_bounds.size()); - ClientAreaSizeToWindowSize(&size); - return gfx::Rect(client_bounds.origin(), size); + return views::GetWindowBoundsForClientBounds( + static_cast(const_cast(this)), + client_bounds); } int WinFrameView::NonClientHitTest(const gfx::Point& point) { @@ -53,12 +53,4 @@ const char* WinFrameView::GetClassName() const { return kViewClassName; } -void WinFrameView::ClientAreaSizeToWindowSize(gfx::Size* size) const { - // AdjustWindowRect seems to return a wrong window size. - gfx::Size window = frame_->GetWindowBoundsInScreen().size(); - gfx::Size client = frame_->GetClientAreaBoundsInScreen().size(); - size->set_width(size->width() + window.width() - client.width()); - size->set_height(size->height() + window.height() - client.height()); -} - } // namespace atom diff --git a/atom/browser/ui/views/win_frame_view.h b/atom/browser/ui/views/win_frame_view.h index 43bab2c8f4..825677bff3 100644 --- a/atom/browser/ui/views/win_frame_view.h +++ b/atom/browser/ui/views/win_frame_view.h @@ -25,8 +25,6 @@ class WinFrameView : public FramelessView { const char* GetClassName() const override; private: - void ClientAreaSizeToWindowSize(gfx::Size* size) const; - DISALLOW_COPY_AND_ASSIGN(WinFrameView); }; From 099eb53d3c7a4be19fd79f11c9ccf52faff300d4 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 12 Dec 2014 10:40:42 -0800 Subject: [PATCH 40/41] Upgrade libchromiumcontent to fix generating node.lib --- script/lib/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/lib/config.py b/script/lib/config.py index d0edf3f65d..c90fc6be4e 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -4,7 +4,7 @@ import platform import sys BASE_URL = 'https://gh-contractor-zcbenz.s3.amazonaws.com/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = 'e4b283c22236560fd289fe59c03e50adf39e7c4b' +LIBCHROMIUMCONTENT_COMMIT = 'aa87035cc012ce0d533bb56b947bca81a6e71b82' ARCH = { 'cygwin': '32bit', From b0a414ea83f72a95e19409445bffcd3d950a3741 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 12 Dec 2014 14:50:39 -0800 Subject: [PATCH 41/41] Upgrade brightray --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index d70727848e..d54838e3f5 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit d70727848e4658ced013aee69dc073a8fcccfcaa +Subproject commit d54838e3f5211e986424f4e82e24f1960b60594a