Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: webkit/port/bindings/v8/v8_proxy.cpp

Issue 10687: Clean up the proxy code for handling frame navigation.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 12 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/port/bindings/v8/v8_proxy.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2008, Google Inc. 1 // Copyright (c) 2008, Google Inc.
2 // All rights reserved. 2 // All rights reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are 5 // modification, are permitted provided that the following conditions are
6 // met: 6 // met:
7 // 7 //
8 // * Redistributions of source code must retain the above copyright 8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer. 9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above 10 // * Redistributions in binary form must reproduce the above
(...skipping 1001 matching lines...) Expand 10 before | Expand all | Expand 10 after
1012 { 1012 {
1013 v8::Local<v8::Context> context = v8::Context::GetCurrent(); 1013 v8::Local<v8::Context> context = v8::Context::GetCurrent();
1014 1014
1015 if (!context->HasOutOfMemoryException()) 1015 if (!context->HasOutOfMemoryException())
1016 return false; 1016 return false;
1017 1017
1018 // Warning, error, disable JS for this frame? 1018 // Warning, error, disable JS for this frame?
1019 Frame* frame = V8Proxy::retrieveFrame(context); 1019 Frame* frame = V8Proxy::retrieveFrame(context);
1020 1020
1021 V8Proxy* proxy = V8Proxy::retrieve(frame); 1021 V8Proxy* proxy = V8Proxy::retrieve(frame);
1022 // Clean m_context, m_document, and event handlers. 1022 // Clean m_context, and event handlers.
1023 proxy->clearForClose(); 1023 proxy->clearForClose();
1024 // Destroy the global object. 1024 // Destroy the global object.
1025 proxy->DestroyGlobal(); 1025 proxy->DestroyGlobal();
1026 1026
1027 webkit_glue::NotifyJSOutOfMemory(frame); 1027 webkit_glue::NotifyJSOutOfMemory(frame);
1028 1028
1029 // Disable JS. 1029 // Disable JS.
1030 Settings* settings = frame->settings(); 1030 Settings* settings = frame->settings();
1031 ASSERT(settings); 1031 ASSERT(settings);
1032 settings->setJavaScriptEnabled(false); 1032 settings->setJavaScriptEnabled(false);
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after
1549 for (size_t i = 0; i < arraysize(kDirProtocols); ++i) { 1549 for (size_t i = 0; i < arraysize(kDirProtocols); ++i) {
1550 if (origin->protocol() == kDirProtocols[i]) { 1550 if (origin->protocol() == kDirProtocols[i]) {
1551 ASSERT(url.SchemeIs(kDirProtocols[i])); 1551 ASSERT(url.SchemeIs(kDirProtocols[i]));
1552 return url.ExtractFileName().empty(); 1552 return url.ExtractFileName().empty();
1553 } 1553 }
1554 } 1554 }
1555 1555
1556 return false; // Other protocols fall through to here 1556 return false; // Other protocols fall through to here
1557 } 1557 }
1558 1558
1559 void V8Proxy::clearDocumentWrapper()
1560 {
1561 v8::Local<v8::Context> context = GetContext();
1562 if (context.IsEmpty())
1563 return; // not initialize yet
1564
1565 if (!m_document.IsEmpty()) {
1566 #ifndef NDEBUG
1567 UnregisterGlobalHandle(this, m_document);
1568 #endif
1569 m_document.Dispose();
1570 m_document.Clear();
1571 }
1572 }
1573 1559
1574 // static 1560 // static
1575 void V8Proxy::DomainChanged(Frame* frame) 1561 void V8Proxy::DomainChanged(Frame* frame)
1576 { 1562 {
1577 V8Proxy* proxy = retrieve(frame); 1563 V8Proxy* proxy = retrieve(frame);
1578 // Restore to default security token. 1564 // Restore to default security token.
1579 proxy->m_context->UseDefaultSecurityToken(); 1565 proxy->m_context->UseDefaultSecurityToken();
1580 } 1566 }
1581 1567
1582 1568
1583 void V8Proxy::clearForClose() 1569 void V8Proxy::clearForClose()
1584 { 1570 {
1585 if (m_context.IsEmpty()) 1571 if (m_context.IsEmpty())
1586 return; 1572 return;
1587 1573
1588 { v8::HandleScope handle_scope;
1589 clearDocumentWrapper();
1590 }
1591
1592 m_context.Dispose(); 1574 m_context.Dispose();
1593 m_context.Clear(); 1575 m_context.Clear();
1594 } 1576 }
1595 1577
1596 1578
1597 void V8Proxy::clearForNavigation() 1579 void V8Proxy::clearForNavigation()
1598 { 1580 {
1599 if (m_context.IsEmpty()) 1581 if (m_context.IsEmpty())
1600 return; 1582 return;
1601 1583
1602 { v8::HandleScope handle; 1584 { v8::HandleScope handle;
1603 clearDocumentWrapper(); 1585
1586 v8::Context::Scope context_scope(m_context);
1604 1587
1605 // Turn on access check on the old DOMWindow wrapper. 1588 // Turn on access check on the old DOMWindow wrapper.
1606 v8::Handle<v8::Object> wrapper = 1589 v8::Handle<v8::Object> wrapper =
1607 LookupDOMWrapper(V8ClassIndex::DOMWINDOW, m_global); 1590 LookupDOMWrapper(V8ClassIndex::DOMWINDOW, m_global);
1608 ASSERT(!wrapper.IsEmpty()); 1591 ASSERT(!wrapper.IsEmpty());
1609 wrapper->TurnOnAccessCheck(); 1592 wrapper->TurnOnAccessCheck();
1610 1593
1611 // Clear all timeouts. 1594 // Clear all timeouts.
1612 DOMWindow* domWindow = 1595 DOMWindow* domWindow =
1613 ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, wrapper); 1596 ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, wrapper);
1614 domWindow->clearAllTimeouts(); 1597 domWindow->clearAllTimeouts();
1615 1598
1616 // disconnect all event listeners 1599 // disconnect all event listeners
1617 DisconnectEventListeners(); 1600 DisconnectEventListeners();
1618 1601
1619 // Separate the context from its global object. 1602 // Separate the context from its global object.
1620 m_context->DetachGlobal(); 1603 m_context->DetachGlobal();
1621 }
1622 1604
1623 // Corresponds to the context creation in initContextIfNeeded(). 1605 m_context.Dispose();
1624 m_context.Dispose(); 1606 m_context.Clear();
1625 m_context.Clear();
1626 }
1627 1607
1628 1608 // Reinitialize the context so the global object points to
1629 void V8Proxy::domWindowReady() 1609 // the new DOM window.
1630 {
1631 // Reinitialize context so the global object is reused by
1632 // the new context.
1633 if (!m_global.IsEmpty() && m_context.IsEmpty()) {
1634 v8::HandleScope scope;
1635 initContextIfNeeded(); 1610 initContextIfNeeded();
1636 } 1611 }
1637 } 1612 }
1638 1613
1639 1614
1615 void V8Proxy::SetSecurityToken() {
1616 Document* document = m_frame->document();
1617 // Setup security origin and security token
1618 if (!document) {
1619 m_context->UseDefaultSecurityToken();
1620 return;
1621 }
1622
1623 // Ask the document's SecurityOrigin to generate a security token.
1624 // If two tokens are equal, then the SecurityOrigins canAccess each other.
1625 // If two tokens are not equal, then we have to call canAccess.
1626 // Note: we can't use the HTTPOrigin if it was set from the DOM.
1627 SecurityOrigin* origin = document->securityOrigin();
1628 String token;
1629 if (!origin->domainWasSetInDOM())
1630 token = document->securityOrigin()->toString();
1631
1632 // An empty token means we always have to call canAccess. In this case, we
1633 // use the global object as the security token to avoid calling canAccess
1634 // when a script accesses its own objects.
1635 if (token.isEmpty()) {
1636 m_context->UseDefaultSecurityToken();
1637 return;
1638 }
1639
1640 CString utf8_token = token.utf8();
1641 // NOTE: V8 does identity comparison in fast path, must use a symbol
1642 // as the security token.
1643 m_context->SetSecurityToken(
1644 v8::String::NewSymbol(utf8_token.data(), utf8_token.length()));
1645
Mike Belshe 2008/11/13 18:13:50 extra line
Feng Qian 2008/11/13 21:30:18 Done.
1646 }
1647
1648
1649 void V8Proxy::updateDocument()
1650 {
1651 if (!m_frame->document())
1652 return;
1653
1654 if (m_global.IsEmpty()) {
1655 ASSERT(m_context.IsEmpty());
1656 return;
1657 }
1658
1659 { v8::HandleScope scope;
Mike Belshe 2008/11/13 18:13:50 funky braces
Feng Qian 2008/11/13 21:30:18 Done.
1660 SetSecurityToken();
1661 }
1662 }
1663
1664
1640 // Check if the current execution context can access a target frame. 1665 // Check if the current execution context can access a target frame.
1641 // First it checks same domain policy using the lexical context 1666 // First it checks same domain policy using the lexical context
1642 // 1667 //
1643 // This is equivalent to KJS::Window::allowsAccessFrom(ExecState*, String&). 1668 // This is equivalent to KJS::Window::allowsAccessFrom(ExecState*, String&).
1644 bool V8Proxy::CanAccessPrivate(DOMWindow* target_window) 1669 bool V8Proxy::CanAccessPrivate(DOMWindow* target_window)
1645 { 1670 {
1646 ASSERT(target_window); 1671 ASSERT(target_window);
1647 1672
1648 String message; 1673 String message;
1649 1674
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1713 1738
1714 Frame* target = node->document()->frame(); 1739 Frame* target = node->document()->frame();
1715 1740
1716 if (!target) 1741 if (!target)
1717 return false; 1742 return false;
1718 1743
1719 return CanAccessFrame(target, true); 1744 return CanAccessFrame(target, true);
1720 } 1745 }
1721 1746
1722 1747
1723 static void GenerateSecurityToken(v8::Local<v8::Context> context)
1724 {
1725 Document* document = V8Proxy::retrieveFrame(context)->document();
1726 if (!document) {
1727 context->UseDefaultSecurityToken();
1728 return;
1729 }
1730
1731 // Ask the document's SecurityOrigin to generate a security token.
1732 // If two tokens are equal, then the SecurityOrigins canAccess each other.
1733 // If two tokens are not equal, then we have to call canAccess.
1734 // Note: we can't use the HTTPOrigin if it was set from the DOM.
1735 SecurityOrigin* origin = document->securityOrigin();
1736 String token;
1737 if (!origin->domainWasSetInDOM())
1738 token = document->securityOrigin()->toString();
1739
1740 // An empty token means we always have to call canAccess. In this case, we
1741 // use the global object as the security token to avoid calling canAccess
1742 // when a script accesses its own objects.
1743 if (token.isEmpty()) {
1744 context->UseDefaultSecurityToken();
1745 return;
1746 }
1747
1748 CString utf8_token = token.utf8();
1749 // NOTE: V8 does identity comparison in fast path, must use a symbol
1750 // as the security token.
1751 context->SetSecurityToken(
1752 v8::String::NewSymbol(utf8_token.data(), utf8_token.length()));
1753 }
1754
1755
1756 // Create a new environment and setup the global object. 1748 // Create a new environment and setup the global object.
1757 // 1749 //
1758 // The global object corresponds to a DOMWindow instance. However, to 1750 // The global object corresponds to a DOMWindow instance. However, to
1759 // allow properties of the JS DOMWindow instance to be shadowed, we 1751 // allow properties of the JS DOMWindow instance to be shadowed, we
1760 // use a shadow object as the global object and use the JS DOMWindow 1752 // use a shadow object as the global object and use the JS DOMWindow
1761 // instance as the prototype for that shadow object. The JS DOMWindow 1753 // instance as the prototype for that shadow object. The JS DOMWindow
1762 // instance is undetectable from javascript code because the __proto__ 1754 // instance is undetectable from javascript code because the __proto__
1763 // accessors skip that object. 1755 // accessors skip that object.
1764 // 1756 //
1765 // The shadow object and the DOMWindow instance are seen as one object 1757 // The shadow object and the DOMWindow instance are seen as one object
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
1865 // Setup the peer object for the DOM window. 1857 // Setup the peer object for the DOM window.
1866 dom_object_map().set(window, v8::Persistent<v8::Object>::New(window_peer)); 1858 dom_object_map().set(window, v8::Persistent<v8::Object>::New(window_peer));
1867 // Wrap the window. 1859 // Wrap the window.
1868 SetDOMWrapper(window_peer, 1860 SetDOMWrapper(window_peer,
1869 V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), 1861 V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW),
1870 window); 1862 window);
1871 // Insert the window instance as the prototype of the shadow object. 1863 // Insert the window instance as the prototype of the shadow object.
1872 v8::Handle<v8::Object> v8_global = context->Global(); 1864 v8::Handle<v8::Object> v8_global = context->Global();
1873 v8_global->Set(v8::String::New("__proto__"), window_peer); 1865 v8_global->Set(v8::String::New("__proto__"), window_peer);
1874 1866
1875 // Setup security origin and security token 1867 SetSecurityToken();
1876 GenerateSecurityToken(context);
1877 1868
1878 m_frame->loader()->dispatchWindowObjectAvailable(); 1869 m_frame->loader()->dispatchWindowObjectAvailable();
1879 1870
1880 if (ScriptController::RecordPlaybackMode()) { 1871 if (ScriptController::RecordPlaybackMode()) {
1881 // Inject code which overrides a few common JS functions for implementing 1872 // Inject code which overrides a few common JS functions for implementing
1882 // randomness. In order to implement effective record & playback of 1873 // randomness. In order to implement effective record & playback of
1883 // websites, it is important that the URLs not change. Many popular web 1874 // websites, it is important that the URLs not change. Many popular web
1884 // based apps use randomness in URLs to unique-ify urls for proxies. 1875 // based apps use randomness in URLs to unique-ify urls for proxies.
1885 // Unfortunately, this breaks playback. 1876 // Unfortunately, this breaks playback.
1886 // To work around this, we take the two most common client-side randomness 1877 // To work around this, we take the two most common client-side randomness
(...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after
2619 // If instantiation failed it's important not to add the result 2610 // If instantiation failed it's important not to add the result
2620 // to the DOM node map. Instead we return an empty handle, which 2611 // to the DOM node map. Instead we return an empty handle, which
2621 // should already be handled by callers of this function in case 2612 // should already be handled by callers of this function in case
2622 // the node is NULL. 2613 // the node is NULL.
2623 return result; 2614 return result;
2624 } 2615 }
2625 2616
2626 dom_node_map().set(node, v8::Persistent<v8::Object>::New(result)); 2617 dom_node_map().set(node, v8::Persistent<v8::Object>::New(result));
2627 2618
2628 if (is_document) { 2619 if (is_document) {
2629 Document* doc = static_cast<Document*>(node);
2630 V8Proxy* proxy = V8Proxy::retrieve(doc->frame());
2631 if (proxy)
2632 proxy->UpdateDocumentHandle(result);
2633
2634 if (type == V8ClassIndex::HTMLDOCUMENT) { 2620 if (type == V8ClassIndex::HTMLDOCUMENT) {
2635 // Create marker object and insert it in two internal fields. 2621 // Create marker object and insert it in two internal fields.
2636 // This is used to implement temporary shadowing of 2622 // This is used to implement temporary shadowing of
2637 // document.all. 2623 // document.all.
2638 ASSERT(result->InternalFieldCount() == 2624 ASSERT(result->InternalFieldCount() ==
2639 V8Custom::kHTMLDocumentInternalFieldCount); 2625 V8Custom::kHTMLDocumentInternalFieldCount);
2640 v8::Local<v8::Object> marker = v8::Object::New(); 2626 v8::Local<v8::Object> marker = v8::Object::New();
2641 result->SetInternalField(V8Custom::kHTMLDocumentMarkerIndex, marker); 2627 result->SetInternalField(V8Custom::kHTMLDocumentMarkerIndex, marker);
2642 result->SetInternalField(V8Custom::kHTMLDocumentShadowIndex, marker); 2628 result->SetInternalField(V8Custom::kHTMLDocumentShadowIndex, marker);
2643 } 2629 }
2644 } 2630 }
2645 2631
2646 return result; 2632 return result;
2647 } 2633 }
2648 2634
2649 2635
2650 void V8Proxy::UpdateDocumentHandle(v8::Local<v8::Object> handle)
2651 {
2652 // If the old handle is not empty, release it.
2653 if (!m_document.IsEmpty()) {
2654 #ifndef NDEBUG
2655 UnregisterGlobalHandle(this, m_document);
2656 #endif
2657 m_document.Dispose();
2658 m_document.Clear();
2659 }
2660
2661 m_document = v8::Persistent<v8::Object>::New(handle);
2662 #ifndef NDEBUG
2663 RegisterGlobalHandle(PROXY, this, m_document);
2664 #endif
2665 }
2666
2667
2668 // A JS object of type EventTarget can only be five possible types: 2636 // A JS object of type EventTarget can only be five possible types:
2669 // 1) EventTargetNode; 2) XMLHttpRequest; 3) MessagePort; 4) SVGElementInstance; 2637 // 1) EventTargetNode; 2) XMLHttpRequest; 3) MessagePort; 4) SVGElementInstance;
2670 // 5) XMLHttpRequestUpload 2638 // 5) XMLHttpRequestUpload
2671 // check EventTarget.h for new type conversion methods 2639 // check EventTarget.h for new type conversion methods
2672 // also make sure to sync with V8EventListener::GetThisObject (v8_events.cpp) 2640 // also make sure to sync with V8EventListener::GetThisObject (v8_events.cpp)
2673 v8::Handle<v8::Value> V8Proxy::EventTargetToV8Object(EventTarget* target) 2641 v8::Handle<v8::Value> V8Proxy::EventTargetToV8Object(EventTarget* target)
2674 { 2642 {
2675 if (!target) 2643 if (!target)
2676 return v8::Null(); 2644 return v8::Null();
2677 2645
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
2894 v8::Handle<v8::Object> global = context->Global(); 2862 v8::Handle<v8::Object> global = context->Global();
2895 global->Set(v8::String::New(name), instance); 2863 global->Set(v8::String::New(name), instance);
2896 } 2864 }
2897 2865
2898 void V8Proxy::ProcessConsoleMessages() 2866 void V8Proxy::ProcessConsoleMessages()
2899 { 2867 {
2900 ConsoleMessageManager::ProcessDelayedMessages(); 2868 ConsoleMessageManager::ProcessDelayedMessages();
2901 } 2869 }
2902 2870
2903 } // namespace WebCore 2871 } // namespace WebCore
OLDNEW
« no previous file with comments | « webkit/port/bindings/v8/v8_proxy.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698