OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "fpdfsdk/javascript/app.h" | 7 #include "fpdfsdk/javascript/app.h" |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "fpdfsdk/include/fsdk_mgr.h" | 12 #include "fpdfsdk/include/fsdk_mgr.h" |
13 #include "fpdfsdk/javascript/Document.h" | 13 #include "fpdfsdk/javascript/Document.h" |
14 #include "fpdfsdk/javascript/JS_Define.h" | 14 #include "fpdfsdk/javascript/JS_Define.h" |
15 #include "fpdfsdk/javascript/JS_EventHandler.h" | 15 #include "fpdfsdk/javascript/JS_EventHandler.h" |
16 #include "fpdfsdk/javascript/JS_Object.h" | 16 #include "fpdfsdk/javascript/JS_Object.h" |
17 #include "fpdfsdk/javascript/JS_Value.h" | 17 #include "fpdfsdk/javascript/JS_Value.h" |
18 #include "fpdfsdk/javascript/cjs_context.h" | 18 #include "fpdfsdk/javascript/cjs_context.h" |
19 #include "fpdfsdk/javascript/cjs_runtime.h" | 19 #include "fpdfsdk/javascript/cjs_runtime.h" |
20 #include "fpdfsdk/javascript/resource.h" | 20 #include "fpdfsdk/javascript/resource.h" |
21 | 21 |
| 22 class GlobalTimer : public CJS_Runtime::Observer { |
| 23 public: |
| 24 GlobalTimer(app* pObj, |
| 25 CPDFDoc_Environment* pApp, |
| 26 CJS_Runtime* pRuntime, |
| 27 int nType, |
| 28 const CFX_WideString& script, |
| 29 uint32_t dwElapse, |
| 30 uint32_t dwTimeOut); |
| 31 ~GlobalTimer() override; |
| 32 |
| 33 static void Trigger(int nTimerID); |
| 34 static void Cancel(int nTimerID); |
| 35 |
| 36 bool IsOneShot() const { return m_nType == 1; } |
| 37 uint32_t GetTimeOut() const { return m_dwTimeOut; } |
| 38 int GetTimerID() const { return m_nTimerID; } |
| 39 CJS_Runtime* GetRuntime() const { return m_bValid ? m_pRuntime : nullptr; } |
| 40 CFX_WideString GetJScript() const { return m_swJScript; } |
| 41 |
| 42 private: |
| 43 using TimerMap = std::map<FX_UINT, GlobalTimer*>; |
| 44 static TimerMap* GetGlobalTimerMap(); |
| 45 |
| 46 // CJS_Runtime::Observer |
| 47 void OnDestroyed() override; |
| 48 |
| 49 uint32_t m_nTimerID; |
| 50 app* const m_pEmbedObj; |
| 51 bool m_bProcessing; |
| 52 bool m_bValid; |
| 53 |
| 54 // data |
| 55 const int m_nType; // 0:Interval; 1:TimeOut |
| 56 const uint32_t m_dwTimeOut; |
| 57 const CFX_WideString m_swJScript; |
| 58 CJS_Runtime* const m_pRuntime; |
| 59 CPDFDoc_Environment* const m_pApp; |
| 60 }; |
| 61 |
| 62 GlobalTimer::GlobalTimer(app* pObj, |
| 63 CPDFDoc_Environment* pApp, |
| 64 CJS_Runtime* pRuntime, |
| 65 int nType, |
| 66 const CFX_WideString& script, |
| 67 uint32_t dwElapse, |
| 68 uint32_t dwTimeOut) |
| 69 : m_nTimerID(0), |
| 70 m_pEmbedObj(pObj), |
| 71 m_bProcessing(false), |
| 72 m_bValid(true), |
| 73 m_nType(nType), |
| 74 m_dwTimeOut(dwTimeOut), |
| 75 m_swJScript(script), |
| 76 m_pRuntime(pRuntime), |
| 77 m_pApp(pApp) { |
| 78 CFX_SystemHandler* pHandler = m_pApp->GetSysHandler(); |
| 79 m_nTimerID = pHandler->SetTimer(dwElapse, Trigger); |
| 80 (*GetGlobalTimerMap())[m_nTimerID] = this; |
| 81 m_pRuntime->AddObserver(this); |
| 82 } |
| 83 |
| 84 GlobalTimer::~GlobalTimer() { |
| 85 CJS_Runtime* pRuntime = GetRuntime(); |
| 86 if (pRuntime) |
| 87 pRuntime->RemoveObserver(this); |
| 88 |
| 89 if (!m_nTimerID) |
| 90 return; |
| 91 |
| 92 if (m_bValid) |
| 93 m_pApp->GetSysHandler()->KillTimer(m_nTimerID); |
| 94 |
| 95 GetGlobalTimerMap()->erase(m_nTimerID); |
| 96 } |
| 97 |
| 98 // static |
| 99 void GlobalTimer::Trigger(int nTimerID) { |
| 100 auto it = GetGlobalTimerMap()->find(nTimerID); |
| 101 if (it == GetGlobalTimerMap()->end()) |
| 102 return; |
| 103 |
| 104 GlobalTimer* pTimer = it->second; |
| 105 if (pTimer->m_bProcessing) |
| 106 return; |
| 107 |
| 108 pTimer->m_bProcessing = true; |
| 109 if (pTimer->m_pEmbedObj) |
| 110 pTimer->m_pEmbedObj->TimerProc(pTimer); |
| 111 |
| 112 // Timer proc may have destroyed timer, find it again. |
| 113 it = GetGlobalTimerMap()->find(nTimerID); |
| 114 if (it == GetGlobalTimerMap()->end()) |
| 115 return; |
| 116 |
| 117 pTimer = it->second; |
| 118 pTimer->m_bProcessing = false; |
| 119 if (pTimer->IsOneShot()) |
| 120 pTimer->m_pEmbedObj->CancelProc(pTimer); |
| 121 } |
| 122 |
| 123 // static |
| 124 void GlobalTimer::Cancel(int nTimerID) { |
| 125 auto it = GetGlobalTimerMap()->find(nTimerID); |
| 126 if (it == GetGlobalTimerMap()->end()) |
| 127 return; |
| 128 |
| 129 GlobalTimer* pTimer = it->second; |
| 130 pTimer->m_pEmbedObj->CancelProc(pTimer); |
| 131 } |
| 132 |
| 133 // static |
| 134 GlobalTimer::TimerMap* GlobalTimer::GetGlobalTimerMap() { |
| 135 // Leak the timer array at shutdown. |
| 136 static auto* s_TimerMap = new TimerMap; |
| 137 return s_TimerMap; |
| 138 } |
| 139 |
| 140 void GlobalTimer::OnDestroyed() { |
| 141 m_bValid = false; |
| 142 } |
| 143 |
22 BEGIN_JS_STATIC_CONST(CJS_TimerObj) | 144 BEGIN_JS_STATIC_CONST(CJS_TimerObj) |
23 END_JS_STATIC_CONST() | 145 END_JS_STATIC_CONST() |
24 | 146 |
25 BEGIN_JS_STATIC_PROP(CJS_TimerObj) | 147 BEGIN_JS_STATIC_PROP(CJS_TimerObj) |
26 END_JS_STATIC_PROP() | 148 END_JS_STATIC_PROP() |
27 | 149 |
28 BEGIN_JS_STATIC_METHOD(CJS_TimerObj) | 150 BEGIN_JS_STATIC_METHOD(CJS_TimerObj) |
29 END_JS_STATIC_METHOD() | 151 END_JS_STATIC_METHOD() |
30 | 152 |
31 IMPLEMENT_JS_CLASS(CJS_TimerObj, TimerObj) | 153 IMPLEMENT_JS_CLASS(CJS_TimerObj, TimerObj) |
32 | 154 |
33 TimerObj::TimerObj(CJS_Object* pJSObject) | 155 TimerObj::TimerObj(CJS_Object* pJSObject) |
34 : CJS_EmbedObj(pJSObject), m_nTimerID(0) {} | 156 : CJS_EmbedObj(pJSObject), m_nTimerID(0) {} |
35 | 157 |
36 TimerObj::~TimerObj() {} | 158 TimerObj::~TimerObj() {} |
37 | 159 |
38 void TimerObj::SetTimer(CJS_Timer* pTimer) { | 160 void TimerObj::SetTimer(GlobalTimer* pTimer) { |
39 m_nTimerID = pTimer->GetTimerID(); | 161 m_nTimerID = pTimer->GetTimerID(); |
40 } | 162 } |
41 | 163 |
42 #define JS_STR_VIEWERTYPE L"pdfium" | 164 #define JS_STR_VIEWERTYPE L"pdfium" |
43 #define JS_STR_VIEWERVARIATION L"Full" | 165 #define JS_STR_VIEWERVARIATION L"Full" |
44 #define JS_STR_PLATFORM L"WIN" | 166 #define JS_STR_PLATFORM L"WIN" |
45 #define JS_STR_LANGUANGE L"ENU" | 167 #define JS_STR_LANGUANGE L"ENU" |
46 #define JS_NUM_VIEWERVERSION 8 | 168 #define JS_NUM_VIEWERVERSION 8 |
47 #ifdef PDF_ENABLE_XFA | 169 #ifdef PDF_ENABLE_XFA |
48 #define JS_NUM_VIEWERVERSION_XFA 11 | 170 #define JS_NUM_VIEWERVERSION_XFA 11 |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 | 490 |
369 CFX_WideString script = params.size() > 0 ? params[0].ToCFXWideString() : L""; | 491 CFX_WideString script = params.size() > 0 ? params[0].ToCFXWideString() : L""; |
370 if (script.IsEmpty()) { | 492 if (script.IsEmpty()) { |
371 sError = JSGetStringFromID(pContext, IDS_STRING_JSAFNUMBER_KEYSTROKE); | 493 sError = JSGetStringFromID(pContext, IDS_STRING_JSAFNUMBER_KEYSTROKE); |
372 return TRUE; | 494 return TRUE; |
373 } | 495 } |
374 | 496 |
375 CJS_Runtime* pRuntime = pContext->GetJSRuntime(); | 497 CJS_Runtime* pRuntime = pContext->GetJSRuntime(); |
376 uint32_t dwInterval = params.size() > 1 ? params[1].ToInt() : 1000; | 498 uint32_t dwInterval = params.size() > 1 ? params[1].ToInt() : 1000; |
377 CPDFDoc_Environment* pApp = pRuntime->GetReaderApp(); | 499 CPDFDoc_Environment* pApp = pRuntime->GetReaderApp(); |
378 m_Timers.push_back(std::unique_ptr<CJS_Timer>( | 500 m_Timers.push_back(std::unique_ptr<GlobalTimer>( |
379 new CJS_Timer(this, pApp, pRuntime, 0, script, dwInterval, 0))); | 501 new GlobalTimer(this, pApp, pRuntime, 0, script, dwInterval, 0))); |
380 | 502 |
381 v8::Local<v8::Object> pRetObj = FXJS_NewFxDynamicObj( | 503 v8::Local<v8::Object> pRetObj = FXJS_NewFxDynamicObj( |
382 pRuntime->GetIsolate(), pRuntime, CJS_TimerObj::g_nObjDefnID); | 504 pRuntime->GetIsolate(), pRuntime, CJS_TimerObj::g_nObjDefnID); |
383 CJS_TimerObj* pJS_TimerObj = static_cast<CJS_TimerObj*>( | 505 CJS_TimerObj* pJS_TimerObj = static_cast<CJS_TimerObj*>( |
384 FXJS_GetPrivate(pRuntime->GetIsolate(), pRetObj)); | 506 FXJS_GetPrivate(pRuntime->GetIsolate(), pRetObj)); |
385 TimerObj* pTimerObj = static_cast<TimerObj*>(pJS_TimerObj->GetEmbedObject()); | 507 TimerObj* pTimerObj = static_cast<TimerObj*>(pJS_TimerObj->GetEmbedObject()); |
386 pTimerObj->SetTimer(m_Timers.back().get()); | 508 pTimerObj->SetTimer(m_Timers.back().get()); |
387 | 509 |
388 vRet = pRetObj; | 510 vRet = pRetObj; |
389 return TRUE; | 511 return TRUE; |
(...skipping 11 matching lines...) Expand all Loading... |
401 | 523 |
402 CFX_WideString script = params[0].ToCFXWideString(); | 524 CFX_WideString script = params[0].ToCFXWideString(); |
403 if (script.IsEmpty()) { | 525 if (script.IsEmpty()) { |
404 sError = JSGetStringFromID(pContext, IDS_STRING_JSAFNUMBER_KEYSTROKE); | 526 sError = JSGetStringFromID(pContext, IDS_STRING_JSAFNUMBER_KEYSTROKE); |
405 return TRUE; | 527 return TRUE; |
406 } | 528 } |
407 | 529 |
408 uint32_t dwTimeOut = params.size() > 1 ? params[1].ToInt() : 1000; | 530 uint32_t dwTimeOut = params.size() > 1 ? params[1].ToInt() : 1000; |
409 CJS_Runtime* pRuntime = pContext->GetJSRuntime(); | 531 CJS_Runtime* pRuntime = pContext->GetJSRuntime(); |
410 CPDFDoc_Environment* pApp = pRuntime->GetReaderApp(); | 532 CPDFDoc_Environment* pApp = pRuntime->GetReaderApp(); |
411 m_Timers.push_back(std::unique_ptr<CJS_Timer>( | 533 m_Timers.push_back(std::unique_ptr<GlobalTimer>( |
412 new CJS_Timer(this, pApp, pRuntime, 1, script, dwTimeOut, dwTimeOut))); | 534 new GlobalTimer(this, pApp, pRuntime, 1, script, dwTimeOut, dwTimeOut))); |
413 | 535 |
414 v8::Local<v8::Object> pRetObj = FXJS_NewFxDynamicObj( | 536 v8::Local<v8::Object> pRetObj = FXJS_NewFxDynamicObj( |
415 pRuntime->GetIsolate(), pRuntime, CJS_TimerObj::g_nObjDefnID); | 537 pRuntime->GetIsolate(), pRuntime, CJS_TimerObj::g_nObjDefnID); |
416 | 538 |
417 CJS_TimerObj* pJS_TimerObj = static_cast<CJS_TimerObj*>( | 539 CJS_TimerObj* pJS_TimerObj = static_cast<CJS_TimerObj*>( |
418 FXJS_GetPrivate(pRuntime->GetIsolate(), pRetObj)); | 540 FXJS_GetPrivate(pRuntime->GetIsolate(), pRetObj)); |
419 | 541 |
420 TimerObj* pTimerObj = static_cast<TimerObj*>(pJS_TimerObj->GetEmbedObject()); | 542 TimerObj* pTimerObj = static_cast<TimerObj*>(pJS_TimerObj->GetEmbedObject()); |
421 pTimerObj->SetTimer(m_Timers.back().get()); | 543 pTimerObj->SetTimer(m_Timers.back().get()); |
422 | 544 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 return; | 583 return; |
462 | 584 |
463 CJS_Object* pJSObj = param.ToCJSObject(); | 585 CJS_Object* pJSObj = param.ToCJSObject(); |
464 if (!pJSObj) | 586 if (!pJSObj) |
465 return; | 587 return; |
466 | 588 |
467 TimerObj* pTimerObj = static_cast<TimerObj*>(pJSObj->GetEmbedObject()); | 589 TimerObj* pTimerObj = static_cast<TimerObj*>(pJSObj->GetEmbedObject()); |
468 if (!pTimerObj) | 590 if (!pTimerObj) |
469 return; | 591 return; |
470 | 592 |
471 CJS_Timer::Cancel(pTimerObj->GetTimerID()); | 593 GlobalTimer::Cancel(pTimerObj->GetTimerID()); |
472 } | 594 } |
473 | 595 |
474 FX_BOOL app::execMenuItem(IJS_Context* cc, | 596 FX_BOOL app::execMenuItem(IJS_Context* cc, |
475 const std::vector<CJS_Value>& params, | 597 const std::vector<CJS_Value>& params, |
476 CJS_Value& vRet, | 598 CJS_Value& vRet, |
477 CFX_WideString& sError) { | 599 CFX_WideString& sError) { |
478 return FALSE; | 600 return FALSE; |
479 } | 601 } |
480 | 602 |
481 void app::TimerProc(CJS_Timer* pTimer) { | 603 void app::TimerProc(GlobalTimer* pTimer) { |
482 CJS_Runtime* pRuntime = pTimer->GetRuntime(); | 604 CJS_Runtime* pRuntime = pTimer->GetRuntime(); |
483 if (pRuntime && (!pTimer->IsOneShot() || pTimer->GetTimeOut() > 0)) | 605 if (pRuntime && (!pTimer->IsOneShot() || pTimer->GetTimeOut() > 0)) |
484 RunJsScript(pRuntime, pTimer->GetJScript()); | 606 RunJsScript(pRuntime, pTimer->GetJScript()); |
485 } | 607 } |
486 | 608 |
487 void app::CancelProc(CJS_Timer* pTimer) { | 609 void app::CancelProc(GlobalTimer* pTimer) { |
488 auto iter = std::find_if(m_Timers.begin(), m_Timers.end(), | 610 auto iter = std::find_if(m_Timers.begin(), m_Timers.end(), |
489 [pTimer](const std::unique_ptr<CJS_Timer>& that) { | 611 [pTimer](const std::unique_ptr<GlobalTimer>& that) { |
490 return pTimer == that.get(); | 612 return pTimer == that.get(); |
491 }); | 613 }); |
492 | 614 |
493 if (iter != m_Timers.end()) | 615 if (iter != m_Timers.end()) |
494 m_Timers.erase(iter); | 616 m_Timers.erase(iter); |
495 } | 617 } |
496 | 618 |
497 void app::RunJsScript(CJS_Runtime* pRuntime, const CFX_WideString& wsScript) { | 619 void app::RunJsScript(CJS_Runtime* pRuntime, const CFX_WideString& wsScript) { |
498 if (!pRuntime->IsBlocking()) { | 620 if (!pRuntime->IsBlocking()) { |
499 IJS_Context* pContext = pRuntime->NewContext(); | 621 IJS_Context* pContext = pRuntime->NewContext(); |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
697 FX_BOOL app::media(IJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError) { | 819 FX_BOOL app::media(IJS_Context* cc, CJS_PropValue& vp, CFX_WideString& sError) { |
698 return FALSE; | 820 return FALSE; |
699 } | 821 } |
700 | 822 |
701 FX_BOOL app::execDialog(IJS_Context* cc, | 823 FX_BOOL app::execDialog(IJS_Context* cc, |
702 const std::vector<CJS_Value>& params, | 824 const std::vector<CJS_Value>& params, |
703 CJS_Value& vRet, | 825 CJS_Value& vRet, |
704 CFX_WideString& sError) { | 826 CFX_WideString& sError) { |
705 return TRUE; | 827 return TRUE; |
706 } | 828 } |
OLD | NEW |