diff options
Diffstat (limited to 'WebCore/platform')
120 files changed, 3031 insertions, 2041 deletions
diff --git a/WebCore/platform/BlobItem.cpp b/WebCore/platform/BlobItem.cpp index a12dd08..cc5e6c7 100644 --- a/WebCore/platform/BlobItem.cpp +++ b/WebCore/platform/BlobItem.cpp @@ -78,6 +78,20 @@ FileBlobItem::FileBlobItem(const String& path) { } +#if ENABLE(DIRECTORY_UPLOAD) +PassRefPtr<BlobItem> FileBlobItem::create(const String& path, const String& relativePath) +{ + return adoptRef(static_cast<BlobItem*>(new FileBlobItem(path, relativePath))); +} + +FileBlobItem::FileBlobItem(const String& path, const String& relativePath) + : m_path(path) + , m_fileName(pathGetFileName(m_path)) + , m_relativePath(relativePath) +{ +} +#endif + unsigned long long FileBlobItem::size() const { // FIXME: synchronized file call @@ -105,144 +119,16 @@ PassRefPtr<BlobItem> FileBlobItem::slice(long long start, long long length) // StringBlobItem -------------------------------------------------------------- -PassRefPtr<BlobItem> StringBlobItem::create(const String& text, LineEnding ending, TextEncoding encoding) -{ - return adoptRef(static_cast<BlobItem*>(new StringBlobItem(text, ending, encoding))); -} - PassRefPtr<BlobItem> StringBlobItem::create(const CString& text) { return adoptRef(static_cast<BlobItem*>(new StringBlobItem(text))); } -StringBlobItem::StringBlobItem(const String& text, LineEnding ending, TextEncoding encoding) - : m_data(StringBlobItem::convertToCString(text, ending, encoding)) -{ -} - StringBlobItem::StringBlobItem(const CString& text) : m_data(text) { } -// Normalize all line-endings to CRLF. -static CString convertToCRLF(const CString& from) -{ - unsigned newLen = 0; - const char* p = from.data(); - while (char c = *p++) { - if (c == '\r') { - // Safe to look ahead because of trailing '\0'. - if (*p != '\n') { - // Turn CR into CRLF. - newLen += 2; - } - } else if (c == '\n') { - // Turn LF into CRLF. - newLen += 2; - } else { - // Leave other characters alone. - newLen += 1; - } - } - if (newLen == from.length()) - return from; - - // Make a copy of the string. - p = from.data(); - char* q; - CString result = CString::newUninitialized(newLen, q); - while (char c = *p++) { - if (c == '\r') { - // Safe to look ahead because of trailing '\0'. - if (*p != '\n') { - // Turn CR into CRLF. - *q++ = '\r'; - *q++ = '\n'; - } - } else if (c == '\n') { - // Turn LF into CRLF. - *q++ = '\r'; - *q++ = '\n'; - } else { - // Leave other characters alone. - *q++ = c; - } - } - return result; -} - -// Normalize all line-endings to CR or LF. -static CString convertToCROrLF(const CString& from, bool toCR) -{ - unsigned newLen = 0; - bool needFix = false; - const char* p = from.data(); - char fromEndingChar = toCR ? '\n' : '\r'; - char toEndingChar = toCR ? '\r' : '\n'; - while (char c = *p++) { - if (c == '\r' && *p == '\n') { - // Turn CRLF into CR or LF. - p++; - needFix = true; - } else if (c == fromEndingChar) { - // Turn CR/LF into LF/CR. - needFix = true; - } - newLen += 1; - } - if (!needFix) - return from; - - // Make a copy of the string. - p = from.data(); - char* q; - CString result = CString::newUninitialized(newLen, q); - while (char c = *p++) { - if (c == '\r' && *p == '\n') { - // Turn CRLF or CR into CR or LF. - p++; - *q++ = toEndingChar; - } else if (c == fromEndingChar) { - // Turn CR/LF into LF/CR. - *q++ = toEndingChar; - } else { - // Leave other characters alone. - *q++ = c; - } - } - return result; -} - -CString StringBlobItem::convertToCString(const String& text, LineEnding ending, TextEncoding encoding) -{ - CString from = encoding.encode(text.characters(), text.length(), EntitiesForUnencodables); - - if (ending == EndingNative) { -#if OS(WINDOWS) - ending = EndingCRLF; -#else - ending = EndingLF; -#endif - } - - switch (ending) { - case EndingTransparent: - return from; - case EndingCRLF: - return convertToCRLF(from); - case EndingCR: - return convertToCROrLF(from, true); - case EndingLF: - return convertToCROrLF(from, false); - default: - ASSERT_NOT_REACHED(); - } - - ASSERT_NOT_REACHED(); - return from; -} - // ByteArrayBlobItem ---------------------------------------------------------- PassRefPtr<BlobItem> ByteArrayBlobItem::create(const char* data, size_t size) diff --git a/WebCore/platform/BlobItem.h b/WebCore/platform/BlobItem.h index 1d34c59..3741f3f 100644 --- a/WebCore/platform/BlobItem.h +++ b/WebCore/platform/BlobItem.h @@ -32,7 +32,6 @@ #define BlobItem_h #include "PlatformString.h" -#include "TextEncoding.h" #include <wtf/OwnPtr.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> @@ -41,15 +40,6 @@ namespace WebCore { -// String ending types. -enum LineEnding { - EndingTransparent = 0, - EndingNative, - EndingLF, - EndingCR, - EndingCRLF, -}; - class ByteArrayBlobItem; class DataBlobItem; class DataRangeBlobItem; @@ -108,8 +98,14 @@ public: class FileBlobItem : public BlobItem { public: static PassRefPtr<BlobItem> create(const String& path); +#if ENABLE(DIRECTORY_UPLOAD) + static PassRefPtr<BlobItem> create(const String& path, const String& relativePath); +#endif virtual const String& name() const { return m_fileName; } virtual const String& path() const { return m_path; } +#if ENABLE(DIRECTORY_UPLOAD) + const String& relativePath() const { return m_relativePath; } +#endif // BlobItem methods. virtual unsigned long long size() const; @@ -120,13 +116,18 @@ public: protected: FileBlobItem(const String& path); +#if ENABLE(DIRECTORY_UPLOAD) + FileBlobItem(const String& path, const String& relativePath); +#endif String m_path; String m_fileName; +#if ENABLE(DIRECTORY_UPLOAD) + String m_relativePath; +#endif }; class StringBlobItem : public DataBlobItem { public: - static PassRefPtr<BlobItem> create(const String&, LineEnding, TextEncoding); static PassRefPtr<BlobItem> create(const CString&); const CString& cstr() const { return m_data; } @@ -138,9 +139,7 @@ public: virtual const char* data() const { return m_data.data(); } private: - StringBlobItem(const String&, LineEnding, TextEncoding); StringBlobItem(const CString&); - static CString convertToCString(const String&, LineEnding, TextEncoding); CString m_data; }; diff --git a/WebCore/platform/Cursor.cpp b/WebCore/platform/Cursor.cpp index 794a9dc..3f17ad9 100644 --- a/WebCore/platform/Cursor.cpp +++ b/WebCore/platform/Cursor.cpp @@ -46,4 +46,477 @@ IntPoint determineHotSpot(Image* image, const IntPoint& specifiedHotSpot) return IntPoint(); } +const Cursor& Cursor::fromType(Cursor::Type type) +{ + switch (type) { + case Cursor::Pointer: + return pointerCursor(); + case Cursor::Cross: + return crossCursor(); + case Cursor::Hand: + return handCursor(); + case Cursor::IBeam: + return iBeamCursor(); + case Cursor::Wait: + return waitCursor(); + case Cursor::Help: + return helpCursor(); + case Cursor::EastResize: + return eastResizeCursor(); + case Cursor::NorthResize: + return northResizeCursor(); + case Cursor::NorthEastResize: + return northEastResizeCursor(); + case Cursor::NorthWestResize: + return northWestResizeCursor(); + case Cursor::SouthResize: + return southResizeCursor(); + case Cursor::SouthEastResize: + return southEastResizeCursor(); + case Cursor::SouthWestResize: + return southWestResizeCursor(); + case Cursor::WestResize: + return westResizeCursor(); + case Cursor::NorthSouthResize: + return northSouthResizeCursor(); + case Cursor::EastWestResize: + return eastWestResizeCursor(); + case Cursor::NorthEastSouthWestResize: + return northEastSouthWestResizeCursor(); + case Cursor::NorthWestSouthEastResize: + return northWestSouthEastResizeCursor(); + case Cursor::ColumnResize: + return columnResizeCursor(); + case Cursor::RowResize: + return rowResizeCursor(); + case Cursor::MiddlePanning: + return middlePanningCursor(); + case Cursor::EastPanning: + return eastPanningCursor(); + case Cursor::NorthPanning: + return northPanningCursor(); + case Cursor::NorthEastPanning: + return northEastPanningCursor(); + case Cursor::NorthWestPanning: + return northWestPanningCursor(); + case Cursor::SouthPanning: + return southPanningCursor(); + case Cursor::SouthEastPanning: + return southEastPanningCursor(); + case Cursor::SouthWestPanning: + return southWestPanningCursor(); + case Cursor::WestPanning: + return westPanningCursor(); + case Cursor::Move: + return moveCursor(); + case Cursor::VerticalText: + return verticalTextCursor(); + case Cursor::Cell: + return cellCursor(); + case Cursor::ContextMenu: + return contextMenuCursor(); + case Cursor::Alias: + return aliasCursor(); + case Cursor::Progress: + return progressCursor(); + case Cursor::NoDrop: + return noDropCursor(); + case Cursor::Copy: + return copyCursor(); + case Cursor::None: + return noneCursor(); + case Cursor::NotAllowed: + return notAllowedCursor(); + case Cursor::ZoomIn: + return zoomInCursor(); + case Cursor::ZoomOut: + return zoomOutCursor(); + case Cursor::Grab: + return grabCursor(); + case Cursor::Grabbing: + return grabbingCursor(); + case Cursor::Custom: + ASSERT_NOT_REACHED(); + } + return pointerCursor(); +} + +const char* nameForCursorType(Cursor::Type type) +{ + switch (type) { + case Cursor::Pointer: + return "Pointer"; + case Cursor::Cross: + return "Cross"; + case Cursor::Hand: + return "Hand"; + case Cursor::IBeam: + return "IBeam"; + case Cursor::Wait: + return "Wait"; + case Cursor::Help: + return "Help"; + case Cursor::EastResize: + return "EastResize"; + case Cursor::NorthResize: + return "NorthResize"; + case Cursor::NorthEastResize: + return "NorthEastResize"; + case Cursor::NorthWestResize: + return "NorthWestResize"; + case Cursor::SouthResize: + return "SouthResize"; + case Cursor::SouthEastResize: + return "SouthEastResize"; + case Cursor::SouthWestResize: + return "SouthWestResize"; + case Cursor::WestResize: + return "WestResize"; + case Cursor::NorthSouthResize: + return "NorthSouthResize"; + case Cursor::EastWestResize: + return "EastWestResize"; + case Cursor::NorthEastSouthWestResize: + return "NorthEastSouthWestResize"; + case Cursor::NorthWestSouthEastResize: + return "NorthWestSouthEastResize"; + case Cursor::ColumnResize: + return "ColumnResize"; + case Cursor::RowResize: + return "RowResize"; + case Cursor::MiddlePanning: + return "MiddlePanning"; + case Cursor::EastPanning: + return "EastPanning"; + case Cursor::NorthPanning: + return "NorthPanning"; + case Cursor::NorthEastPanning: + return "NorthEastPanning"; + case Cursor::NorthWestPanning: + return "NorthWestPanning"; + case Cursor::SouthPanning: + return "SouthPanning"; + case Cursor::SouthEastPanning: + return "SouthEastPanning"; + case Cursor::SouthWestPanning: + return "SouthWestPanning"; + case Cursor::WestPanning: + return "WestPanning"; + case Cursor::Move: + return "Move"; + case Cursor::VerticalText: + return "VerticalText"; + case Cursor::Cell: + return "Cell"; + case Cursor::ContextMenu: + return "ContextMenu"; + case Cursor::Alias: + return "Alias"; + case Cursor::Progress: + return "Progress"; + case Cursor::NoDrop: + return "NoDrop"; + case Cursor::Copy: + return "Copy"; + case Cursor::None: + return "None"; + case Cursor::NotAllowed: + return "NotAllowed"; + case Cursor::ZoomIn: + return "ZoomIn"; + case Cursor::ZoomOut: + return "ZoomOut"; + case Cursor::Grab: + return "Grab"; + case Cursor::Grabbing: + return "Grabbing"; + case Cursor::Custom: + return "Custom"; + } + + return "ERROR"; +} + +#if USE(LAZY_NATIVE_CURSOR) + +Cursor::Cursor(Image* image, const IntPoint& hotSpot) + : m_type(Custom) + , m_image(image) + , m_hotSpot(determineHotSpot(image, hotSpot)) + , m_platformCursor(0) +{ +} + +Cursor::Cursor(Type type) + : m_type(type) + , m_platformCursor(0) +{ +} + +PlatformCursor Cursor::platformCursor() const +{ + ensurePlatformCursor(); + return m_platformCursor; +} + +const Cursor& pointerCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Pointer)); + return c; +} + +const Cursor& crossCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Cross)); + return c; +} + +const Cursor& handCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Hand)); + return c; +} + +const Cursor& moveCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Move)); + return c; +} + +const Cursor& verticalTextCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::VerticalText)); + return c; +} + +const Cursor& cellCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Cell)); + return c; +} + +const Cursor& contextMenuCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ContextMenu)); + return c; +} + +const Cursor& aliasCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Alias)); + return c; +} + +const Cursor& zoomInCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ZoomIn)); + return c; +} + +const Cursor& zoomOutCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ZoomOut)); + return c; +} + +const Cursor& copyCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Copy)); + return c; +} + +const Cursor& noneCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::None)); + return c; +} + +const Cursor& progressCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Progress)); + return c; +} + +const Cursor& noDropCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NoDrop)); + return c; +} + +const Cursor& notAllowedCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NotAllowed)); + return c; +} + +const Cursor& iBeamCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::IBeam)); + return c; +} + +const Cursor& waitCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Wait)); + return c; +} + +const Cursor& helpCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Help)); + return c; } + +const Cursor& eastResizeCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::EastResize)); + return c; +} + +const Cursor& northResizeCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthResize)); + return c; +} + +const Cursor& northEastResizeCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthEastResize)); + return c; +} + +const Cursor& northWestResizeCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthWestResize)); + return c; +} + +const Cursor& southResizeCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthResize)); + return c; +} + +const Cursor& southEastResizeCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthEastResize)); + return c; +} + +const Cursor& southWestResizeCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthWestResize)); + return c; +} + +const Cursor& westResizeCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::WestResize)); + return c; +} + +const Cursor& northSouthResizeCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthSouthResize)); + return c; +} + +const Cursor& eastWestResizeCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::EastWestResize)); + return c; +} + +const Cursor& northEastSouthWestResizeCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthEastSouthWestResize)); + return c; +} + +const Cursor& northWestSouthEastResizeCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthWestSouthEastResize)); + return c; +} + +const Cursor& columnResizeCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ColumnResize)); + return c; +} + +const Cursor& rowResizeCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::RowResize)); + return c; +} + +const Cursor& middlePanningCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::MiddlePanning)); + return c; +} + +const Cursor& eastPanningCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::EastPanning)); + return c; +} + +const Cursor& northPanningCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthPanning)); + return c; +} + +const Cursor& northEastPanningCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthEastPanning)); + return c; +} + +const Cursor& northWestPanningCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthWestPanning)); + return c; +} + +const Cursor& southPanningCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthPanning)); + return c; +} + +const Cursor& southEastPanningCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthEastPanning)); + return c; +} + +const Cursor& southWestPanningCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthWestPanning)); + return c; +} + +const Cursor& westPanningCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::WestPanning)); + return c; +} + +const Cursor& grabCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Grab)); + return c; +} + +const Cursor& grabbingCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Grabbing)); + return c; +} + +#endif + +} // namespace WebCore diff --git a/WebCore/platform/Cursor.h b/WebCore/platform/Cursor.h index 12b1614..98d69b9 100644 --- a/WebCore/platform/Cursor.h +++ b/WebCore/platform/Cursor.h @@ -26,12 +26,15 @@ #ifndef Cursor_h #define Cursor_h +#include "Image.h" +#include "IntPoint.h" +#include <wtf/RefPtr.h> + #if PLATFORM(WIN) typedef struct HICON__* HICON; typedef HICON HCURSOR; #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> #elif PLATFORM(GTK) typedef struct _GdkCursor GdkCursor; #elif PLATFORM(QT) @@ -59,10 +62,13 @@ typedef struct HICON__ *HICON; typedef HICON HCURSOR; #endif +#if PLATFORM(WIN) || PLATFORM(MAC) +#define WTF_USE_LAZY_NATIVE_CURSOR 1 +#endif + namespace WebCore { class Image; - class IntPoint; #if PLATFORM(WIN) class SharedCursor : public RefCounted<SharedCursor> { @@ -75,55 +81,113 @@ namespace WebCore { HCURSOR m_nativeCursor; }; typedef RefPtr<SharedCursor> PlatformCursor; - typedef HCURSOR PlatformCursorHandle; #elif PLATFORM(MAC) typedef NSCursor* PlatformCursor; - typedef NSCursor* PlatformCursorHandle; #elif PLATFORM(GTK) typedef GdkCursor* PlatformCursor; - typedef GdkCursor* PlatformCursorHandle; #elif PLATFORM(EFL) typedef const char* PlatformCursor; - typedef const char* PlatformCursorHandle; #elif PLATFORM(QT) && !defined(QT_NO_CURSOR) typedef QCursor PlatformCursor; - typedef QCursor* PlatformCursorHandle; #elif PLATFORM(WX) typedef wxCursor* PlatformCursor; - typedef wxCursor* PlatformCursorHandle; #elif PLATFORM(CHROMIUM) // See PlatformCursor.h - typedef void* PlatformCursorHandle; #elif PLATFORM(HAIKU) typedef BCursor* PlatformCursor; - typedef BCursor* PlatformCursorHandle; #else typedef void* PlatformCursor; - typedef void* PlatformCursorHandle; #endif class Cursor { public: + enum Type { + Pointer, + Cross, + Hand, + IBeam, + Wait, + Help, + EastResize, + NorthResize, + NorthEastResize, + NorthWestResize, + SouthResize, + SouthEastResize, + SouthWestResize, + WestResize, + NorthSouthResize, + EastWestResize, + NorthEastSouthWestResize, + NorthWestSouthEastResize, + ColumnResize, + RowResize, + MiddlePanning, + EastPanning, + NorthPanning, + NorthEastPanning, + NorthWestPanning, + SouthPanning, + SouthEastPanning, + SouthWestPanning, + WestPanning, + Move, + VerticalText, + Cell, + ContextMenu, + Alias, + Progress, + NoDrop, + Copy, + None, + NotAllowed, + ZoomIn, + ZoomOut, + Grab, + Grabbing, + Custom + }; + + static const Cursor& fromType(Cursor::Type); + Cursor() #if !PLATFORM(QT) && !PLATFORM(EFL) - : m_impl(0) + : m_platformCursor(0) #endif - { } + { + } Cursor(Image*, const IntPoint& hotSpot); Cursor(const Cursor&); ~Cursor(); Cursor& operator=(const Cursor&); +#if USE(LAZY_NATIVE_CURSOR) + Cursor(Type); + Type type() const { return m_type; } + Image* image() const { return m_image.get(); } + const IntPoint& hotSpot() const { return m_hotSpot; } + PlatformCursor platformCursor() const; +#else Cursor(PlatformCursor); - PlatformCursor impl() const { return m_impl; } + PlatformCursor impl() const { return m_platformCursor; } +#endif private: - PlatformCursor m_impl; +#if USE(LAZY_NATIVE_CURSOR) + void ensurePlatformCursor() const; + + Type m_type; + RefPtr<Image> m_image; + IntPoint m_hotSpot; +#endif + + mutable PlatformCursor m_platformCursor; }; IntPoint determineHotSpot(Image*, const IntPoint& specifiedHotSpot); - + const char* nameForCursorType(Cursor::Type); + const Cursor& pointerCursor(); const Cursor& crossCursor(); const Cursor& handCursor(); diff --git a/WebCore/platform/FileChooser.h b/WebCore/platform/FileChooser.h index e93b9ac..fa25406 100644 --- a/WebCore/platform/FileChooser.h +++ b/WebCore/platform/FileChooser.h @@ -44,6 +44,9 @@ public: virtual void valueChanged() = 0; virtual void repaint() = 0; virtual bool allowsMultipleFiles() = 0; +#if ENABLE(DIRECTORY_UPLOAD) + virtual bool allowsDirectoryUpload() = 0; +#endif virtual String acceptTypes() = 0; virtual void chooseIconForFiles(FileChooser*, const Vector<String>&) = 0; virtual ~FileChooserClient(); @@ -70,6 +73,9 @@ public: void iconLoaded(PassRefPtr<Icon>); bool allowsMultipleFiles() const { return m_client ? m_client->allowsMultipleFiles() : false; } +#if ENABLE(DIRECTORY_UPLOAD) + bool allowsDirectoryUpload() const { return m_client ? m_client->allowsDirectoryUpload() : false; } +#endif // Acceptable MIME types. It's an 'accept' attribute value of the corresponding INPUT element. String acceptTypes() const { return m_client ? m_client->acceptTypes() : String(); } diff --git a/WebCore/platform/HostWindow.h b/WebCore/platform/HostWindow.h index e7316a7..b0ee653 100644 --- a/WebCore/platform/HostWindow.h +++ b/WebCore/platform/HostWindow.h @@ -31,6 +31,8 @@ namespace WebCore { +class Cursor; + class HostWindow : public Noncopyable { public: virtual ~HostWindow() { } @@ -56,6 +58,9 @@ public: // To notify WebKit of scrollbar mode changes. virtual void scrollbarsModeDidChange() const = 0; + + // Request that the cursor change. + virtual void setCursor(const Cursor&) = 0; }; } // namespace WebCore diff --git a/WebCore/platform/KURLGoogle.cpp b/WebCore/platform/KURLGoogle.cpp index b4c84a6..ac02630 100644 --- a/WebCore/platform/KURLGoogle.cpp +++ b/WebCore/platform/KURLGoogle.cpp @@ -48,7 +48,6 @@ #include <wtf/StdLibExtras.h> #include <wtf/text/CString.h> -#include <googleurl/src/url_canon_internal.h> #include <googleurl/src/url_util.h> using WTF::isASCIILower; @@ -943,55 +942,13 @@ String decodeURLEscapeSequences(const String& str, const TextEncoding& encoding) const char* input = cstr.data(); int inputLength = cstr.length(); - url_canon::RawCanonOutputT<char> unescaped; - for (int i = 0; i < inputLength; i++) { - if (input[i] == '%') { - unsigned char ch; - if (url_canon::DecodeEscaped(input, &i, inputLength, &ch)) - unescaped.push_back(ch); - else { - // Invalid escape sequence, copy the percent literal. - unescaped.push_back('%'); - } - } else { - // Regular non-escaped 8-bit character. - unescaped.push_back(input[i]); - } - } - // Convert that 8-bit to UTF-16. It's not clear IE does this at all to - // JavaScript URLs, but Firefox and Safari do. - url_canon::RawCanonOutputT<url_parse::UTF16Char> utf16; - for (int i = 0; i < unescaped.length(); i++) { - unsigned char uch = static_cast<unsigned char>(unescaped.at(i)); - if (uch < 0x80) { - // Non-UTF-8, just append directly - utf16.push_back(uch); - } else { - // next_ch will point to the last character of the decoded - // character. - int nextCharacter = i; - unsigned codePoint; - if (url_canon::ReadUTFChar(unescaped.data(), &nextCharacter, - unescaped.length(), &codePoint)) { - // Valid UTF-8 character, convert to UTF-16. - url_canon::AppendUTF16Value(codePoint, &utf16); - i = nextCharacter; - } else { - // KURL.cpp strips any sequences that are not valid UTF-8. This - // sounds scary. Instead, we just keep those invalid code - // points and promote to UTF-16. We copy all characters from - // the current position to the end of the identified sqeuqnce. - while (i < nextCharacter) { - utf16.push_back(static_cast<unsigned char>(unescaped.at(i))); - i++; - } - utf16.push_back(static_cast<unsigned char>(unescaped.at(i))); - } - } - } + url_canon::RawCanonOutputT<url_parse::UTF16Char> unescaped; + + url_util::DecodeURLEscapeSequences(input, inputLength, &unescaped); - return String(reinterpret_cast<UChar*>(utf16.data()), utf16.length()); + return String(reinterpret_cast<UChar*>(unescaped.data()), + unescaped.length()); } bool KURL::protocolIs(const char* protocol) const diff --git a/WebCore/platform/MIMETypeRegistry.cpp b/WebCore/platform/MIMETypeRegistry.cpp index d6ff588..e6eb209 100644 --- a/WebCore/platform/MIMETypeRegistry.cpp +++ b/WebCore/platform/MIMETypeRegistry.cpp @@ -302,6 +302,7 @@ static MediaMIMETypeMap& mediaMIMETypeMap() { "audio/x-m4a", "m4a" }, { "audio/x-m4b", "m4b" }, { "audio/x-m4p", "m4p" }, + { "audio/mp4", "m4a" }, // MP3 { "audio/mp3", "mp3" }, diff --git a/WebCore/platform/PopupMenuClient.h b/WebCore/platform/PopupMenuClient.h index bffde92..a1396e8 100644 --- a/WebCore/platform/PopupMenuClient.h +++ b/WebCore/platform/PopupMenuClient.h @@ -42,6 +42,7 @@ public: virtual void selectionCleared() = 0; virtual String itemText(unsigned listIndex) const = 0; + virtual String itemLabel(unsigned listIndex) const = 0; virtual String itemToolTip(unsigned listIndex) const = 0; virtual String itemAccessibilityText(unsigned listIndex) const = 0; virtual bool itemIsEnabled(unsigned listIndex) const = 0; diff --git a/WebCore/platform/Widget.h b/WebCore/platform/Widget.h index 45da67a..6303c6a 100644 --- a/WebCore/platform/Widget.h +++ b/WebCore/platform/Widget.h @@ -187,8 +187,8 @@ public: virtual bool isFrameView() const { return false; } virtual bool isPluginView() const { return false; } - // FIXME: The Mac plug-in code should inherit from PluginView. When this happens PluginWidget and PluginView can become one class. - virtual bool isPluginWidget() const { return false; } + // FIXME: The Mac plug-in code should inherit from PluginView. When this happens PluginViewBase and PluginView can become one class. + virtual bool isPluginViewBase() const { return false; } virtual bool isScrollbar() const { return false; } void removeFromParent(); diff --git a/WebCore/platform/android/TemporaryLinkStubs.cpp b/WebCore/platform/android/TemporaryLinkStubs.cpp index 302a1ed..911d849 100644 --- a/WebCore/platform/android/TemporaryLinkStubs.cpp +++ b/WebCore/platform/android/TemporaryLinkStubs.cpp @@ -65,7 +65,6 @@ #include "PageCache.h" #include "Pasteboard.h" #include "Path.h" -#include "PluginWidget.h" #include "ResourceError.h" #include "ResourceHandle.h" #include "ResourceLoader.h" @@ -103,10 +102,6 @@ String WebCore::defaultLanguage() namespace WebCore { -// Needed to link with PluginWidget as a parent class of PluginToggleWidget. Mac -// defines this in plugins/mac/PluginWidgetMac.mm -void PluginWidget::invalidateRect(const IntRect&) { } - // This function tells the bridge that a resource was loaded from the cache and thus // the app may update progress with the amount of data loaded. void CheckCacheObjectStatus(DocLoader*, CachedResource*) @@ -478,12 +473,6 @@ void AXObjectCache::remove(RenderObject*) notImplemented(); } -const AtomicString& AccessibilityObject::getAttribute(Node*, const QualifiedName&) -{ - static const AtomicString emptyString; - return emptyString; -} - #if USE(JSC) using namespace JSC; diff --git a/WebCore/platform/brew/PopupMenuBrew.cpp b/WebCore/platform/brew/PopupMenuBrew.cpp index 89f3fa1..eb03c66 100644 --- a/WebCore/platform/brew/PopupMenuBrew.cpp +++ b/WebCore/platform/brew/PopupMenuBrew.cpp @@ -40,6 +40,9 @@ PopupMenu::PopupMenu(PopupMenuClient* menuList) PopupMenu::~PopupMenu() { + // Tell client to destroy data related to this popup since this object is + // going away. + hide(); } void PopupMenu::show(const IntRect& rect, FrameView* view, int index) diff --git a/WebCore/platform/chromium/ChromiumBridge.h b/WebCore/platform/chromium/ChromiumBridge.h index 3284aae..2d9695e 100644 --- a/WebCore/platform/chromium/ChromiumBridge.h +++ b/WebCore/platform/chromium/ChromiumBridge.h @@ -241,6 +241,8 @@ namespace WebCore { GraphicsContext*, int part, int state, int classicState, const IntRect&); static void paintScrollbarTrack( GraphicsContext*, int part, int state, int classicState, const IntRect&, const IntRect& alignRect); + static void paintSpinButton( + GraphicsContext*, int part, int state, int classicState, const IntRect&); static void paintTextField( GraphicsContext*, int part, int state, int classicState, const IntRect&, const Color&, bool fillContentArea, bool drawEdges); static void paintTrackbar( diff --git a/WebCore/platform/chromium/CursorChromium.cpp b/WebCore/platform/chromium/CursorChromium.cpp index 16fa634..0119f07 100644 --- a/WebCore/platform/chromium/CursorChromium.cpp +++ b/WebCore/platform/chromium/CursorChromium.cpp @@ -34,12 +34,12 @@ namespace WebCore { Cursor::Cursor(const Cursor& other) - : m_impl(other.m_impl) + : m_platformCursor(other.m_platformCursor) { } Cursor::Cursor(Image* image, const IntPoint& hotSpot) - : m_impl(image, hotSpot) + : m_platformCursor(image, hotSpot) { } @@ -49,12 +49,12 @@ Cursor::~Cursor() Cursor& Cursor::operator=(const Cursor& other) { - m_impl = other.m_impl; + m_platformCursor = other.m_platformCursor; return *this; } Cursor::Cursor(PlatformCursor c) - : m_impl(c) + : m_platformCursor(c) { } diff --git a/WebCore/platform/chromium/GLES2Context.h b/WebCore/platform/chromium/GLES2Context.h index b72329a..d37885a 100644 --- a/WebCore/platform/chromium/GLES2Context.h +++ b/WebCore/platform/chromium/GLES2Context.h @@ -43,14 +43,8 @@ class Page; class GLES2Context : public Noncopyable { public: - // Creates a GL ES context that draws directly to the window associated with - // the Page. - static PassOwnPtr<GLES2Context> createOnscreen(Page*); - - // Creates a GL ES context that renders offscreen, optionally as a child - // of the given parent if specified. - static PassOwnPtr<GLES2Context> createOffscreen(GLES2Context* parent); - + // Used by the implementation only + static PassOwnPtr<GLES2Context> create(PassOwnPtr<GLES2ContextInternal>); ~GLES2Context(); bool makeCurrent(); @@ -65,6 +59,8 @@ public: unsigned getOffscreenContentParentTextureId(); private: + GLES2Context(); + friend class GLES2ContextInternal; OwnPtr<GLES2ContextInternal> m_internal; }; diff --git a/WebCore/platform/chromium/PlatformThemeChromiumGtk.cpp b/WebCore/platform/chromium/PlatformThemeChromiumGtk.cpp new file mode 100644 index 0000000..1f74840 --- /dev/null +++ b/WebCore/platform/chromium/PlatformThemeChromiumGtk.cpp @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "PlatformThemeChromiumGtk.h" + +namespace WebCore { + +unsigned PlatformThemeChromiumGtk::s_thumbInactiveColor = 0xeaeaea; +unsigned PlatformThemeChromiumGtk::s_thumbActiveColor = 0xf4f4f4; +unsigned PlatformThemeChromiumGtk::s_trackColor = 0xd3d3d3; + +void PlatformThemeChromiumGtk::setScrollbarColors( + SkColor inactiveColor, SkColor activeColor, SkColor trackColor) +{ + s_thumbInactiveColor = inactiveColor; + s_thumbActiveColor = activeColor; + s_trackColor = trackColor; +} + +static SkScalar clamp(SkScalar value, SkScalar min, SkScalar max) +{ + return std::min(std::max(value, min), max); +} + +SkColor PlatformThemeChromiumGtk::saturateAndBrighten(const SkScalar hsv[3], SkScalar saturateAmount, SkScalar brightenAmount) +{ + SkScalar color[3]; + color[0] = hsv[0]; + color[1] = clamp(hsv[1] + saturateAmount, 0.0, 1.0); + color[2] = clamp(hsv[2] + brightenAmount, 0.0, 1.0); + return SkHSVToColor(color); +} + +SkColor PlatformThemeChromiumGtk::outlineColor(const SkScalar hsv1[3], const SkScalar hsv2[3]) +{ + // GTK Theme engines have way too much control over the layout of + // the scrollbar. We might be able to more closely approximate its + // look-and-feel, if we sent whole images instead of just colors + // from the browser to the renderer. But even then, some themes + // would just break. + // + // So, instead, we don't even try to 100% replicate the look of + // the native scrollbar. We render our own version, but we make + // sure to pick colors that blend in nicely with the system GTK + // theme. In most cases, we can just sample a couple of pixels + // from the system scrollbar and use those colors to draw our + // scrollbar. + // + // This works fine for the track color and the overall thumb + // color. But it fails spectacularly for the outline color used + // around the thumb piece. Not all themes have a clearly defined + // outline. For some of them it is partially transparent, and for + // others the thickness is very unpredictable. + // + // So, instead of trying to approximate the system theme, we + // instead try to compute a reasonable looking choice based on the + // known color of the track and the thumb piece. This is difficult + // when trying to deal both with high- and low-contrast themes, + // and both with positive and inverted themes. + // + // The following code has been tested to look OK with all of the + // default GTK themes. + SkScalar minDiff = clamp((hsv1[1] + hsv2[1]) * 1.2, 0.28, 0.5); + SkScalar diff = clamp(fabs(hsv1[2] - hsv2[2]) / 2, minDiff, 0.5); + + if (hsv1[2] + hsv2[2] > 1.0) + diff = -diff; + + return saturateAndBrighten(hsv2, -0.2, diff); +} + +void PlatformThemeChromiumGtk::paintArrowButton(GraphicsContext* gc, const IntRect& rect, ArrowDirection direction, ControlStates states) +{ + SkCanvas* const canvas = gc->platformContext()->canvas(); + int widthMiddle, lengthMiddle; + SkPaint paint; + if (direction == North || direction == South) { + widthMiddle = rect.width() / 2 + 1; + lengthMiddle = rect.height() / 2 + 1; + } else { + lengthMiddle = rect.width() / 2 + 1; + widthMiddle = rect.height() / 2 + 1; + } + + // Calculate button color. + SkScalar trackHSV[3]; + SkColorToHSV(trackColor(), trackHSV); + SkColor buttonColor = saturateAndBrighten(trackHSV, 0, 0.2); + SkColor backgroundColor = buttonColor; + if (states & PressedState) { + SkScalar buttonHSV[3]; + SkColorToHSV(buttonColor, buttonHSV); + buttonColor = saturateAndBrighten(buttonHSV, 0, -0.1); + } else if (states & HoverState) { + SkScalar buttonHSV[3]; + SkColorToHSV(buttonColor, buttonHSV); + buttonColor = saturateAndBrighten(buttonHSV, 0, 0.05); + } + + SkIRect skrect; + skrect.set(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height()); + // Paint the background (the area visible behind the rounded corners). + paint.setColor(backgroundColor); + canvas->drawIRect(skrect, paint); + + // Paint the button's outline and fill the middle + SkPath outline; + switch (direction) { + case North: + outline.moveTo(rect.x() + 0.5, rect.y() + rect.height() + 0.5); + outline.rLineTo(0, -(rect.height() - 2)); + outline.rLineTo(2, -2); + outline.rLineTo(rect.width() - 5, 0); + outline.rLineTo(2, 2); + outline.rLineTo(0, rect.height() - 2); + break; + case South: + outline.moveTo(rect.x() + 0.5, rect.y() - 0.5); + outline.rLineTo(0, rect.height() - 2); + outline.rLineTo(2, 2); + outline.rLineTo(rect.width() - 5, 0); + outline.rLineTo(2, -2); + outline.rLineTo(0, -(rect.height() - 2)); + break; + case East: + outline.moveTo(rect.x() - 0.5, rect.y() + 0.5); + outline.rLineTo(rect.width() - 2, 0); + outline.rLineTo(2, 2); + outline.rLineTo(0, rect.height() - 5); + outline.rLineTo(-2, 2); + outline.rLineTo(-(rect.width() - 2), 0); + break; + case West: + outline.moveTo(rect.x() + rect.width() + 0.5, rect.y() + 0.5); + outline.rLineTo(-(rect.width() - 2), 0); + outline.rLineTo(-2, 2); + outline.rLineTo(0, rect.height() - 5); + outline.rLineTo(2, 2); + outline.rLineTo(rect.width() - 2, 0); + break; + } + outline.close(); + + paint.setStyle(SkPaint::kFill_Style); + paint.setColor(buttonColor); + canvas->drawPath(outline, paint); + + paint.setAntiAlias(true); + paint.setStyle(SkPaint::kStroke_Style); + SkScalar thumbHSV[3]; + SkColorToHSV(thumbInactiveColor(), thumbHSV); + paint.setColor(outlineColor(trackHSV, thumbHSV)); + canvas->drawPath(outline, paint); + + // If the button is disabled, the arrow is drawn with the outline color. + if (states & EnabledState) + paint.setColor(SK_ColorBLACK); + + paint.setAntiAlias(false); + paint.setStyle(SkPaint::kFill_Style); + + SkPath path; + // The constants in this block of code are hand-tailored to produce good + // looking arrows without anti-aliasing. + switch (direction) { + case North: + path.moveTo(rect.x() + widthMiddle - 4, rect.y() + lengthMiddle + 2); + path.rLineTo(7, 0); + path.rLineTo(-4, -4); + break; + case South: + path.moveTo(rect.x() + widthMiddle - 4, rect.y() + lengthMiddle - 3); + path.rLineTo(7, 0); + path.rLineTo(-4, 4); + break; + case East: + path.moveTo(rect.x() + lengthMiddle - 3, rect.y() + widthMiddle - 4); + path.rLineTo(0, 7); + path.rLineTo(4, -4); + break; + case West: + path.moveTo(rect.x() + lengthMiddle + 1, rect.y() + widthMiddle - 5); + path.rLineTo(0, 9); + path.rLineTo(-4, -4); + break; + } + path.close(); + + canvas->drawPath(path, paint); +} + +} // namespace WebCore + diff --git a/WebCore/platform/chromium/PlatformThemeChromiumGtk.h b/WebCore/platform/chromium/PlatformThemeChromiumGtk.h new file mode 100644 index 0000000..bdc2683 --- /dev/null +++ b/WebCore/platform/chromium/PlatformThemeChromiumGtk.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PlatformThemeChromiumGtk_h +#define PlatformThemeChromiumGtk_h + +#include "PlatformContextSkia.h" +#include "SkColor.h" +#include "SkScalar.h" +#include "ThemeTypes.h" + +namespace WebCore { + +class PlatformThemeChromiumGtk { +public: + enum ArrowDirection { + North, + East, + South, + West, + }; + + static void setScrollbarColors(unsigned inactiveColor, + unsigned activeColor, + unsigned trackColor); + static unsigned thumbInactiveColor() { return s_thumbInactiveColor; } + static unsigned thumbActiveColor() { return s_thumbActiveColor; } + static unsigned trackColor() { return s_trackColor; } + + static SkColor saturateAndBrighten(const SkScalar hsv[3], SkScalar saturateAmount, SkScalar brightenAmount); + static SkColor outlineColor(const SkScalar hsv1[3], const SkScalar hsv2[3]); + static void paintArrowButton(GraphicsContext*, const IntRect&, ArrowDirection, ControlStates); + +private: + PlatformThemeChromiumGtk() {} + + static unsigned s_thumbInactiveColor; + static unsigned s_thumbActiveColor; + static unsigned s_trackColor; +}; + +} // namespace WebCore + +#endif // PlatformThemeChromiumGtk_h diff --git a/WebCore/platform/chromium/PopupMenuChromium.cpp b/WebCore/platform/chromium/PopupMenuChromium.cpp index 7e3a2a0..4701a75 100644 --- a/WebCore/platform/chromium/PopupMenuChromium.cpp +++ b/WebCore/platform/chromium/PopupMenuChromium.cpp @@ -70,6 +70,7 @@ typedef unsigned long long TimeStamp; static const int kMaxVisibleRows = 20; static const int kMaxHeight = 500; static const int kBorderSize = 1; +static const int kTextToLabelPadding = 10; static const TimeStamp kTypeAheadTimeoutMs = 1000; // The settings used for the drop down menu. @@ -751,8 +752,11 @@ bool PopupListBox::handleKeyEvent(const PlatformKeyboardEvent& event) if (event.windowsVirtualKeyCode() == VKEY_TAB) { // TAB is a special case as it should select the current item if any and // advance focus. - if (m_selectedIndex >= 0) - m_popupClient->setTextFromItem(m_selectedIndex); + if (m_selectedIndex >= 0) { + acceptIndex(m_selectedIndex); // May delete us. + // Return false so the TAB key event is propagated to the page. + return false; + } // Call abandon() so we honor m_acceptedIndexOnAbandon if set. abandon(); // Return false so the TAB key event is propagated to the page. @@ -873,13 +877,17 @@ void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowInd PopupMenuStyle style = m_popupClient->itemStyle(rowIndex); // Paint background - Color backColor, textColor; + Color backColor, textColor, labelColor; if (rowIndex == m_selectedIndex) { backColor = RenderTheme::defaultTheme()->activeListBoxSelectionBackgroundColor(); textColor = RenderTheme::defaultTheme()->activeListBoxSelectionForegroundColor(); + labelColor = textColor; } else { backColor = style.backgroundColor(); textColor = style.foregroundColor(); + // FIXME: for now the label color is hard-coded. It should be added to + // the PopupMenuStyle. + labelColor = Color(115, 115, 115); } // If we have a transparent background, make sure it has a color to blend @@ -917,10 +925,23 @@ void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowInd } // Prepare text to be drawn. String itemText = m_popupClient->itemText(rowIndex); - if (m_settings.restrictWidthOfListBox) // truncate string to fit in. - itemText = StringTruncator::rightTruncate(itemText, maxWidth, itemFont); - unsigned length = itemText.length(); - const UChar* str = itemText.characters(); + String itemLabel = m_popupClient->itemLabel(rowIndex); + if (m_settings.restrictWidthOfListBox) { // Truncate strings to fit in. + // FIXME: We should leftTruncate for the rtl case. + // StringTruncator::leftTruncate would have to be implemented. + String str = StringTruncator::rightTruncate(itemText, maxWidth, itemFont); + if (str != itemText) { + itemText = str; + // Don't display the label, we already don't have enough room for the + // item text. + itemLabel = ""; + } else if (!itemLabel.isEmpty()) { + int availableWidth = maxWidth - kTextToLabelPadding - + StringTruncator::width(itemText, itemFont); + itemLabel = StringTruncator::rightTruncate(itemLabel, availableWidth, itemFont); + } + } + // Prepare the directionality to draw text. bool rtl = false; if (m_settings.itemTextDirectionalityHint == PopupContainerSettings::DOMElementDirection) @@ -928,14 +949,31 @@ void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowInd else if (m_settings.itemTextDirectionalityHint == PopupContainerSettings::FirstStrongDirectionalCharacterDirection) rtl = itemText.defaultWritingDirection() == WTF::Unicode::RightToLeft; - TextRun textRun(str, length, false, 0, 0, rtl); + TextRun textRun(itemText.characters(), itemText.length(), false, 0, 0, rtl); // If the text is right-to-left, make it right-aligned by adjusting its // beginning position. if (rightAligned) textX += maxWidth - itemFont.width(textRun); + // Draw the item text. int textY = rowRect.y() + itemFont.ascent() + (rowRect.height() - itemFont.height()) / 2; gc->drawBidiText(itemFont, textRun, IntPoint(textX, textY)); + + // Draw the the label if applicable. + if (itemLabel.isEmpty()) + return; + TextRun labelTextRun(itemLabel.characters(), itemLabel.length(), false, 0, 0, rtl); + if (rightAligned) + textX = max(0, m_popupClient->clientPaddingLeft() - m_popupClient->clientInsetLeft()); + else { + // We are using the left padding as the right padding includes room for the scroll-bar which + // does not show in this case. + int rightPadding = max(0, m_popupClient->clientPaddingLeft() - m_popupClient->clientInsetLeft()); + textX = rowRect.width() - rightPadding - itemFont.width(labelTextRun); + } + + gc->setFillColor(labelColor, DeviceColorSpace); + gc->drawBidiText(itemFont, labelTextRun, IntPoint(textX, textY)); } Font PopupListBox::getRowFont(int rowIndex) diff --git a/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp b/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp index a9cff9f..19b4a54 100644 --- a/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp +++ b/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp @@ -33,8 +33,7 @@ #include "PlatformContextSkia.h" #include "PlatformMouseEvent.h" -#include "RenderTheme.h" -#include "RenderThemeChromiumLinux.h" +#include "PlatformThemeChromiumGtk.h" #include "Scrollbar.h" #include "TransformationMatrix.h" @@ -78,60 +77,6 @@ static void drawBox(SkCanvas* canvas, const IntRect& rect, const SkPaint& paint) drawVertLine(canvas, rect.x(), rect.y(), bottom, paint); } -static SkScalar clamp(SkScalar value, SkScalar min, SkScalar max) -{ - return std::min(std::max(value, min), max); -} - -static SkColor saturateAndBrighten(SkScalar* hsv, - SkScalar saturateAmount, - SkScalar brightenAmount) -{ - SkScalar color[3]; - color[0] = hsv[0]; - color[1] = clamp(hsv[1] + saturateAmount, 0.0, 1.0); - color[2] = clamp(hsv[2] + brightenAmount, 0.0, 1.0); - return SkHSVToColor(color); -} - -static SkColor outlineColor(SkScalar* hsv1, SkScalar* hsv2) -{ - // GTK Theme engines have way too much control over the layout of - // the scrollbar. We might be able to more closely approximate its - // look-and-feel, if we sent whole images instead of just colors - // from the browser to the renderer. But even then, some themes - // would just break. - // - // So, instead, we don't even try to 100% replicate the look of - // the native scrollbar. We render our own version, but we make - // sure to pick colors that blend in nicely with the system GTK - // theme. In most cases, we can just sample a couple of pixels - // from the system scrollbar and use those colors to draw our - // scrollbar. - // - // This works fine for the track color and the overall thumb - // color. But it fails spectacularly for the outline color used - // around the thumb piece. Not all themes have a clearly defined - // outline. For some of them it is partially transparent, and for - // others the thickness is very unpredictable. - // - // So, instead of trying to approximate the system theme, we - // instead try to compute a reasonable looking choice based on the - // known color of the track and the thumb piece. This is difficult - // when trying to deal both with high- and low-contrast themes, - // and both with positive and inverted themes. - // - // The following code has been tested to look OK with all of the - // default GTK themes. - SkScalar minDiff = clamp((hsv1[1] + hsv2[1]) * 1.2, 0.28, 0.5); - SkScalar diff = clamp(fabs(hsv1[2] - hsv2[2]) / 2, minDiff, 0.5); - - if (hsv1[2] + hsv2[2] > 1.0) - diff = -diff; - - return saturateAndBrighten(hsv2, -0.2, diff); -} - void ScrollbarThemeChromiumLinux::paintTrackPiece(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart partType) { SkCanvas* const canvas = gc->platformContext()->canvas(); @@ -140,154 +85,47 @@ void ScrollbarThemeChromiumLinux::paintTrackPiece(GraphicsContext* gc, Scrollbar skrect.set(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height()); SkScalar trackHSV[3]; - SkColorToHSV(RenderThemeChromiumLinux::trackColor(), trackHSV); - paint.setColor(saturateAndBrighten(trackHSV, 0, 0)); + SkColorToHSV(PlatformThemeChromiumGtk::trackColor(), trackHSV); + paint.setColor(PlatformThemeChromiumGtk::saturateAndBrighten(trackHSV, 0, 0)); canvas->drawIRect(skrect, paint); SkScalar thumbHSV[3]; - SkColorToHSV(RenderThemeChromiumLinux::thumbInactiveColor(), + SkColorToHSV(PlatformThemeChromiumGtk::thumbInactiveColor(), thumbHSV); - paint.setColor(outlineColor(trackHSV, thumbHSV)); + paint.setColor(PlatformThemeChromiumGtk::outlineColor(trackHSV, thumbHSV)); drawBox(canvas, rect, paint); } void ScrollbarThemeChromiumLinux::paintButton(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart part) { - SkCanvas* const canvas = gc->platformContext()->canvas(); - static const int widthMiddle = scrollbarThicknessValue / 2 + 1; - static const int lengthMiddle = buttonLength / 2 + 1; - SkPaint paint; - enum { - North, - East, - South, - West, - } direction; - + PlatformThemeChromiumGtk::ArrowDirection direction; if (scrollbar->orientation() == HorizontalScrollbar) { if (part == BackButtonStartPart) - direction = West; + direction = PlatformThemeChromiumGtk::West; else - direction = East; + direction = PlatformThemeChromiumGtk::East; } else { if (part == BackButtonStartPart) - direction = North; + direction = PlatformThemeChromiumGtk::North; else - direction = South; + direction = PlatformThemeChromiumGtk::South; } + ControlStates states = 0; // Determine if the button can be pressed. - bool enabled = false; - if (((direction == West || direction == North) && scrollbar->currentPos()) - || (direction == East || direction == South) && scrollbar->currentPos() != scrollbar->maximum()) - enabled = true; - - // Calculate button color. - SkScalar trackHSV[3]; - SkColorToHSV(RenderThemeChromiumLinux::trackColor(), trackHSV); - SkColor buttonColor = saturateAndBrighten(trackHSV, 0, 0.2); - SkColor backgroundColor = buttonColor; - if (part == scrollbar->pressedPart()) { - SkScalar buttonHSV[3]; - SkColorToHSV(buttonColor, buttonHSV); - buttonColor = saturateAndBrighten(buttonHSV, 0, -0.1); - } else if (part == scrollbar->hoveredPart() && enabled) { - SkScalar buttonHSV[3]; - SkColorToHSV(buttonColor, buttonHSV); - buttonColor = saturateAndBrighten(buttonHSV, 0, 0.05); - } - - SkIRect skrect; - skrect.set(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height()); - // Paint the background (the area visible behind the rounded corners). - paint.setColor(backgroundColor); - canvas->drawIRect(skrect, paint); - - // Paint the button's outline and fill the middle - SkPath outline; - switch (direction) { - case North: - outline.moveTo(rect.x() + 0.5, rect.y() + rect.height() + 0.5); - outline.rLineTo(0, -(rect.height() - 2)); - outline.rLineTo(2, -2); - outline.rLineTo(rect.width() - 5, 0); - outline.rLineTo(2, 2); - outline.rLineTo(0, rect.height() - 2); - break; - case South: - outline.moveTo(rect.x() + 0.5, rect.y() - 0.5); - outline.rLineTo(0, rect.height() - 2); - outline.rLineTo(2, 2); - outline.rLineTo(rect.width() - 5, 0); - outline.rLineTo(2, -2); - outline.rLineTo(0, -(rect.height() - 2)); - break; - case East: - outline.moveTo(rect.x() - 0.5, rect.y() + 0.5); - outline.rLineTo(rect.width() - 2, 0); - outline.rLineTo(2, 2); - outline.rLineTo(0, rect.height() - 5); - outline.rLineTo(-2, 2); - outline.rLineTo(-(rect.width() - 2), 0); - break; - case West: - outline.moveTo(rect.x() + rect.width() + 0.5, rect.y() + 0.5); - outline.rLineTo(-(rect.width() - 2), 0); - outline.rLineTo(-2, 2); - outline.rLineTo(0, rect.height() - 5); - outline.rLineTo(2, 2); - outline.rLineTo(rect.width() - 2, 0); - break; - } - outline.close(); - - paint.setStyle(SkPaint::kFill_Style); - paint.setColor(buttonColor); - canvas->drawPath(outline, paint); - - paint.setAntiAlias(true); - paint.setStyle(SkPaint::kStroke_Style); - SkScalar thumbHSV[3]; - SkColorToHSV(RenderThemeChromiumLinux::thumbInactiveColor(), thumbHSV); - paint.setColor(outlineColor(trackHSV, thumbHSV)); - canvas->drawPath(outline, paint); - - // If the button is disabled, the arrow is drawn with the outline color. - if (enabled) - paint.setColor(SK_ColorBLACK); - - paint.setAntiAlias(false); - paint.setStyle(SkPaint::kFill_Style); - - SkPath path; - // The constants in this block of code are hand-tailored to produce good - // looking arrows without anti-aliasing. - switch (direction) { - case North: - path.moveTo(rect.x() + widthMiddle - 4, rect.y() + lengthMiddle + 2); - path.rLineTo(7, 0); - path.rLineTo(-4, -4); - break; - case South: - path.moveTo(rect.x() + widthMiddle - 4, rect.y() + lengthMiddle - 3); - path.rLineTo(7, 0); - path.rLineTo(-4, 4); - break; - case East: - path.moveTo(rect.x() + lengthMiddle - 3, rect.y() + widthMiddle - 4); - path.rLineTo(0, 7); - path.rLineTo(4, -4); - break; - case West: - path.moveTo(rect.x() + lengthMiddle + 1, rect.y() + widthMiddle - 5); - path.rLineTo(0, 9); - path.rLineTo(-4, -4); - break; + if (((direction == PlatformThemeChromiumGtk::West || direction == PlatformThemeChromiumGtk::North) && scrollbar->currentPos()) + || (direction == PlatformThemeChromiumGtk::East || direction == PlatformThemeChromiumGtk::South) && scrollbar->currentPos() != scrollbar->maximum()) + states |= EnabledState; + + if (states & EnabledState) { + if (part == scrollbar->pressedPart()) + states |= PressedState; + else if (part == scrollbar->hoveredPart()) + states |= HoverState; } - path.close(); - canvas->drawPath(path, paint); + PlatformThemeChromiumGtk::paintArrowButton(gc, rect, direction, states); } void ScrollbarThemeChromiumLinux::paintThumb(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect) @@ -300,12 +138,12 @@ void ScrollbarThemeChromiumLinux::paintThumb(GraphicsContext* gc, Scrollbar* scr SkScalar thumb[3]; SkColorToHSV(hovered - ? RenderThemeChromiumLinux::thumbActiveColor() - : RenderThemeChromiumLinux::thumbInactiveColor(), + ? PlatformThemeChromiumGtk::thumbActiveColor() + : PlatformThemeChromiumGtk::thumbInactiveColor(), thumb); SkPaint paint; - paint.setColor(saturateAndBrighten(thumb, 0, 0.02)); + paint.setColor(PlatformThemeChromiumGtk::saturateAndBrighten(thumb, 0, 0.02)); SkIRect skrect; if (vertical) @@ -315,7 +153,7 @@ void ScrollbarThemeChromiumLinux::paintThumb(GraphicsContext* gc, Scrollbar* scr canvas->drawIRect(skrect, paint); - paint.setColor(saturateAndBrighten(thumb, 0, -0.02)); + paint.setColor(PlatformThemeChromiumGtk::saturateAndBrighten(thumb, 0, -0.02)); if (vertical) skrect.set(midx + 1, rect.y(), rect.x() + rect.width(), rect.y() + rect.height()); @@ -325,8 +163,8 @@ void ScrollbarThemeChromiumLinux::paintThumb(GraphicsContext* gc, Scrollbar* scr canvas->drawIRect(skrect, paint); SkScalar track[3]; - SkColorToHSV(RenderThemeChromiumLinux::trackColor(), track); - paint.setColor(outlineColor(track, thumb)); + SkColorToHSV(PlatformThemeChromiumGtk::trackColor(), track); + paint.setColor(PlatformThemeChromiumGtk::outlineColor(track, thumb)); drawBox(canvas, rect, paint); if (rect.height() > 10 && rect.width() > 10) { diff --git a/WebCore/platform/chromium/ThemeChromiumMac.mm b/WebCore/platform/chromium/ThemeChromiumMac.mm index 5769e38..68fd7b7 100644 --- a/WebCore/platform/chromium/ThemeChromiumMac.mm +++ b/WebCore/platform/chromium/ThemeChromiumMac.mm @@ -32,6 +32,7 @@ #import "LocalCurrentGraphicsContext.h" #import "ScrollView.h" #import "WebCoreSystemInterface.h" +#import <Carbon/Carbon.h> #include <wtf/StdLibExtras.h> #import <objc/runtime.h> @@ -210,9 +211,9 @@ static NSControlSize controlSizeForFont(const Font& font) return NSMiniControlSize; } -static LengthSize sizeFromFont(const Font& font, const LengthSize& zoomedSize, float zoomFactor, const IntSize* sizes) +static LengthSize sizeFromNSControlSize(NSControlSize nsControlSize, const LengthSize& zoomedSize, float zoomFactor, const IntSize* sizes) { - IntSize controlSize = sizes[controlSizeForFont(font)]; + IntSize controlSize = sizes[nsControlSize]; if (zoomFactor != 1.0f) controlSize = IntSize(controlSize.width() * zoomFactor, controlSize.height() * zoomFactor); LengthSize result = zoomedSize; @@ -223,19 +224,27 @@ static LengthSize sizeFromFont(const Font& font, const LengthSize& zoomedSize, f return result; } -static void setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minZoomedSize, float zoomFactor) +static LengthSize sizeFromFont(const Font& font, const LengthSize& zoomedSize, float zoomFactor, const IntSize* sizes) +{ + return sizeFromNSControlSize(controlSizeForFont(font), zoomedSize, zoomFactor, sizes); +} + +static ControlSize controlSizeFromPixelSize(const IntSize* sizes, const IntSize& minZoomedSize, float zoomFactor) { - NSControlSize size; if (minZoomedSize.width() >= static_cast<int>(sizes[NSRegularControlSize].width() * zoomFactor) && minZoomedSize.height() >= static_cast<int>(sizes[NSRegularControlSize].height() * zoomFactor)) - size = NSRegularControlSize; - else if (minZoomedSize.width() >= static_cast<int>(sizes[NSSmallControlSize].width() * zoomFactor) && - minZoomedSize.height() >= static_cast<int>(sizes[NSSmallControlSize].height() * zoomFactor)) - size = NSSmallControlSize; - else - size = NSMiniControlSize; + return NSRegularControlSize; + if (minZoomedSize.width() >= static_cast<int>(sizes[NSSmallControlSize].width() * zoomFactor) && + minZoomedSize.height() >= static_cast<int>(sizes[NSSmallControlSize].height() * zoomFactor)) + return NSSmallControlSize; + return NSMiniControlSize; +} + +static void setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minZoomedSize, float zoomFactor) +{ + ControlSize size = controlSizeFromPixelSize(sizes, minZoomedSize, zoomFactor); if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same. - [cell setControlSize:size]; + [cell setControlSize:(NSControlSize)size]; } static void updateStates(NSCell* cell, ControlStates states) @@ -277,6 +286,22 @@ static void updateStates(NSCell* cell, ControlStates states) [cell setControlTint:tint]; } +static ThemeDrawState convertControlStatesToThemeDrawState(ThemeButtonKind kind, ControlStates states) +{ + if (states & ReadOnlyState) + return kThemeStateUnavailableInactive; + if (!(states & EnabledState)) + return kThemeStateUnavailableInactive; + + // Do not process PressedState if !EnabledState or ReadOnlyState. + if (states & PressedState) { + if (kind == kThemeIncDecButton || kind == kThemeIncDecButtonSmall || kind == kThemeIncDecButtonMini) + return states & SpinUpState ? kThemeStatePressedUp : kThemeStatePressedDown; + return kThemeStatePressed; + } + return kThemeStateActive; +} + static IntRect inflateRect(const IntRect& zoomedRect, const IntSize& zoomedSize, const int* margins, float zoomFactor) { // Only do the inflation if the available width/height are too small. Otherwise try to @@ -571,6 +596,64 @@ static void paintButton(ControlPart part, ControlStates states, GraphicsContext* END_BLOCK_OBJC_EXCEPTIONS } +// Stepper + +static const IntSize* stepperSizes() +{ + static const IntSize sizes[3] = { IntSize(19, 27), IntSize(15, 22), IntSize(13, 15) }; + return sizes; +} + +// We don't use controlSizeForFont() for steppers because the stepper height +// should be equal to or less than the corresponding text field height, +static NSControlSize stepperControlSizeForFont(const Font& font) +{ + int fontSize = font.pixelSize(); + if (fontSize >= 18) + return NSRegularControlSize; + if (fontSize >= 13) + return NSSmallControlSize; + return NSMiniControlSize; +} + +static void paintStepper(ControlStates states, GraphicsContext* context, const IntRect& zoomedRect, float zoomFactor, ScrollView*) +{ + // We don't use NSStepperCell because there are no ways to draw an + // NSStepperCell with the up button highlighted. + + HIThemeButtonDrawInfo drawInfo; + drawInfo.version = 0; + drawInfo.state = convertControlStatesToThemeDrawState(kThemeIncDecButton, states); + drawInfo.adornment = kThemeAdornmentDefault; + ControlSize controlSize = controlSizeFromPixelSize(stepperSizes(), zoomedRect.size(), zoomFactor); + if (controlSize == NSSmallControlSize) + drawInfo.kind = kThemeIncDecButtonSmall; + else if (controlSize == NSMiniControlSize) + drawInfo.kind = kThemeIncDecButtonMini; + else + drawInfo.kind = kThemeIncDecButton; + + IntRect rect(zoomedRect); + context->save(); + if (zoomFactor != 1.0f) { + rect.setWidth(rect.width() / zoomFactor); + rect.setHeight(rect.height() / zoomFactor); + context->translate(rect.x(), rect.y()); + context->scale(FloatSize(zoomFactor, zoomFactor)); + context->translate(-rect.x(), -rect.y()); + } + CGRect bounds(rect); + // Adjust 'bounds' so that HIThemeDrawButton(bounds,...) draws exactly on 'rect'. + CGRect backgroundBounds; + HIThemeGetButtonBackgroundBounds(&bounds, &drawInfo, &backgroundBounds); + if (bounds.origin.x != backgroundBounds.origin.x) + bounds.origin.x += bounds.origin.x - backgroundBounds.origin.x; + if (bounds.origin.y != backgroundBounds.origin.y) + bounds.origin.y += bounds.origin.y - backgroundBounds.origin.y; + HIThemeDrawButton(&bounds, &drawInfo, context->platformContext(), kHIThemeOrientationNormal, 0); + context->restore(); +} + // Theme overrides int ThemeChromiumMac::baselinePositionAdjustment(ControlPart part) const @@ -613,6 +696,13 @@ LengthSize ThemeChromiumMac::controlSize(ControlPart part, const Font& font, con case ListButtonPart: return sizeFromFont(font, LengthSize(zoomedSize.width(), Length()), zoomFactor, listButtonSizes()); #endif + case InnerSpinButtonPart: + // We don't use inner spin buttons on Mac. + return LengthSize(Length(Fixed), Length(Fixed)); + case OuterSpinButtonPart: + if (!zoomedSize.width().isIntrinsicOrAuto() && !zoomedSize.height().isIntrinsicOrAuto()) + return zoomedSize; + return sizeFromNSControlSize(stepperControlSizeForFont(font), zoomedSize, zoomFactor, stepperSizes()); default: return zoomedSize; } @@ -626,6 +716,14 @@ LengthSize ThemeChromiumMac::minimumControlSize(ControlPart part, const Font& fo case ButtonPart: case ListButtonPart: return LengthSize(Length(0, Fixed), Length(static_cast<int>(15 * zoomFactor), Fixed)); + case InnerSpinButtonPart: + // We don't use inner spin buttons on Mac. + return LengthSize(Length(Fixed), Length(Fixed)); + case OuterSpinButtonPart: { + IntSize base = stepperSizes()[NSMiniControlSize]; + return LengthSize(Length(static_cast<int>(base.width() * zoomFactor), Fixed), + Length(static_cast<int>(base.height() * zoomFactor), Fixed)); + } default: return Theme::minimumControlSize(part, font, zoomFactor); } @@ -702,6 +800,15 @@ void ThemeChromiumMac::inflateControlPaintRect(ControlPart part, ControlStates s } break; } + case OuterSpinButtonPart: { + static const int stepperMargin[4] = { 0, 0, 0, 0 }; + ControlSize controlSize = controlSizeFromPixelSize(stepperSizes(), zoomedRect.size(), zoomFactor); + IntSize zoomedSize = stepperSizes()[controlSize]; + zoomedSize.setHeight(zoomedSize.height() * zoomFactor); + zoomedSize.setWidth(zoomedSize.width() * zoomFactor); + zoomedRect = inflateRect(zoomedRect, zoomedSize, stepperMargin, zoomFactor); + break; + } default: break; } @@ -724,6 +831,9 @@ void ThemeChromiumMac::paint(ControlPart part, ControlStates states, GraphicsCon case ListButtonPart: paintButton(part, states, context, zoomedRect, zoomFactor, scrollView); break; + case OuterSpinButtonPart: + paintStepper(states, context, zoomedRect, zoomFactor, scrollView); + break; default: break; } diff --git a/WebCore/platform/efl/CursorEfl.cpp b/WebCore/platform/efl/CursorEfl.cpp index c88830e..47141f9 100644 --- a/WebCore/platform/efl/CursorEfl.cpp +++ b/WebCore/platform/efl/CursorEfl.cpp @@ -45,33 +45,33 @@ namespace WebCore { Cursor::Cursor(PlatformCursor p) { - m_impl = eina_stringshare_add(p); + m_platformCursor = eina_stringshare_add(p); } Cursor::Cursor(const Cursor& other) { - m_impl = eina_stringshare_ref(other.m_impl); + m_platformCursor = eina_stringshare_ref(other.m_platformCursor); } Cursor::~Cursor() { - if (m_impl) { - eina_stringshare_del(m_impl); - m_impl = 0; + if (m_platformCursor) { + eina_stringshare_del(m_platformCursor); + m_platformCursor = 0; } } Cursor::Cursor(Image* image, const IntPoint& hotspot) - : m_impl(0) + : m_platformCursor(0) { notImplemented(); } Cursor& Cursor::operator=(const Cursor& other) { - eina_stringshare_ref(other.m_impl); - eina_stringshare_del(m_impl); - m_impl = other.m_impl; + eina_stringshare_ref(other.m_platformCursor); + eina_stringshare_del(m_platformCursor); + m_platformCursor = other.m_platformCursor; return *this; } diff --git a/WebCore/platform/efl/PopupMenuEfl.cpp b/WebCore/platform/efl/PopupMenuEfl.cpp index 4d9677b..9dc6986 100644 --- a/WebCore/platform/efl/PopupMenuEfl.cpp +++ b/WebCore/platform/efl/PopupMenuEfl.cpp @@ -39,6 +39,9 @@ PopupMenu::PopupMenu(PopupMenuClient* client) PopupMenu::~PopupMenu() { + // Tell client to destroy data related to this popup since this object is + // going away. + hide(); } void PopupMenu::show(const IntRect& rect, FrameView* view, int index) diff --git a/WebCore/platform/efl/SoundEfl.cpp b/WebCore/platform/efl/SoundEfl.cpp index c3b1eb3..091de7a 100644 --- a/WebCore/platform/efl/SoundEfl.cpp +++ b/WebCore/platform/efl/SoundEfl.cpp @@ -32,7 +32,6 @@ #ifdef HAVE_ECORE_X #include <Ecore_X.h> -#include <X11/Xlib.h> #endif namespace WebCore { @@ -40,8 +39,7 @@ namespace WebCore { void systemBeep() { #ifdef HAVE_ECORE_X - Display* display = (Display*) ecore_x_display_get(); - XBell(display, 0); + ecore_x_bell(0); #endif } diff --git a/WebCore/platform/efl/WidgetEfl.cpp b/WebCore/platform/efl/WidgetEfl.cpp index 725e56f..6dbf2c2 100644 --- a/WebCore/platform/efl/WidgetEfl.cpp +++ b/WebCore/platform/efl/WidgetEfl.cpp @@ -211,8 +211,8 @@ void Widget::applyFallbackCursor() int shape = cursorStringMap.cursor(m_data->m_cursorGroup.utf8().data()); if (shape < ECORE_X_CURSOR_X || shape > ECORE_X_CURSOR_XTERM) { - fprintf(stderr, "ERROR: cannot map an equivalent X cursor for" - " cursor group %s", m_data->m_cursorGroup.utf8().data()); + LOG_ERROR("cannot map an equivalent X cursor for" + " c ursor group %s", m_data->m_cursorGroup.utf8().data()); shape = ECORE_X_CURSOR_LEFT_PTR; } @@ -221,29 +221,23 @@ void Widget::applyFallbackCursor() ecore_x_window_cursor_set(win, cur); return; } -#else - fprintf(stderr, "ERROR: Ooops, no fallback to set cursor %s!\n", - m_data->m_cursorGroup.utf8().data()); #endif + LOG("Ooops, no fallback to set cursor %s!\n", + m_data->m_cursorGroup.utf8().data()); } void Widget::applyCursor() { - const char *file = 0; - Evas_Coord x, y; - - String theme = edjeThemeRecursive(); - if (!theme.isNull()) - file = edjeThemeRecursive().utf8().data(); + CString file = edjeThemeRecursive().utf8(); m_data->m_cursorObject = edje_object_add(evas()); - if (file && !edje_object_file_set(m_data->m_cursorObject, file, m_data->m_cursorGroup.utf8().data())) { + if (!file.isNull() && !edje_object_file_set(m_data->m_cursorObject, file.data(), m_data->m_cursorGroup.utf8().data())) { evas_object_del(m_data->m_cursorObject); m_data->m_cursorObject = 0; ecore_evas_object_cursor_set(ecoreEvas(), 0, 0, 0, 0); applyFallbackCursor(); } else { - Evas_Coord w, h; + Evas_Coord x, y, w, h; const char *d; edje_object_size_min_get(m_data->m_cursorObject, &w, &h); @@ -266,7 +260,7 @@ void Widget::applyCursor() void Widget::setCursor(const Cursor& cursor) { - if (!platformWidget() || !evas()) + if (!evas()) return; const char *group = cursor.impl(); @@ -347,7 +341,9 @@ void Widget::setEvasObject(Evas_Object *o) m_data->m_evasObject = o; if (!o) { m_data->m_evas = 0; +#ifdef HAVE_ECORE_X m_data->m_isUsingEcoreX = false; +#endif return; } diff --git a/WebCore/platform/graphics/Color.h b/WebCore/platform/graphics/Color.h index 089d061..9335bc4 100644 --- a/WebCore/platform/graphics/Color.h +++ b/WebCore/platform/graphics/Color.h @@ -69,6 +69,11 @@ RGBA32 makeRGBAFromCMYKA(float c, float m, float y, float k, float a); int differenceSquared(const Color&, const Color&); +inline int redChannel(RGBA32 color) { return (color >> 16) & 0xFF; } +inline int greenChannel(RGBA32 color) { return (color >> 8) & 0xFF; } +inline int blueChannel(RGBA32 color) { return color & 0xFF; } +inline int alphaChannel(RGBA32 color) { return (color >> 24) & 0xFF; } + class Color : public FastAllocBase { public: Color() : m_color(0), m_valid(false) { } @@ -93,10 +98,10 @@ public: bool hasAlpha() const { return alpha() < 255; } - int red() const { return (m_color >> 16) & 0xFF; } - int green() const { return (m_color >> 8) & 0xFF; } - int blue() const { return m_color & 0xFF; } - int alpha() const { return (m_color >> 24) & 0xFF; } + int red() const { return redChannel(m_color); } + int green() const { return greenChannel(m_color); } + int blue() const { return blueChannel(m_color); } + int alpha() const { return alphaChannel(m_color); } RGBA32 rgb() const { return m_color; } // Preserve the alpha. void setRGB(int r, int g, int b) { m_color = makeRGB(r, g, b); m_valid = true; } diff --git a/WebCore/platform/graphics/FloatPoint.h b/WebCore/platform/graphics/FloatPoint.h index 7443e97..5018f1d 100644 --- a/WebCore/platform/graphics/FloatPoint.h +++ b/WebCore/platform/graphics/FloatPoint.h @@ -80,7 +80,16 @@ public: void setX(float x) { m_x = x; } void setY(float y) { m_y = y; } - void move(float dx, float dy) { m_x += dx; m_y += dy; } + void move(float dx, float dy) + { + m_x += dx; + m_y += dy; + } + void scale(float sx, float sy) + { + m_x *= sx; + m_y *= sy; + } #if PLATFORM(CG) FloatPoint(const CGPoint&); @@ -122,6 +131,12 @@ inline FloatPoint& operator+=(FloatPoint& a, const FloatSize& b) return a; } +inline FloatPoint& operator+=(FloatPoint& a, const FloatPoint& b) +{ + a.move(b.x(), b.y()); + return a; +} + inline FloatPoint& operator-=(FloatPoint& a, const FloatSize& b) { a.move(-b.width(), -b.height()); @@ -133,6 +148,11 @@ inline FloatPoint operator+(const FloatPoint& a, const FloatSize& b) return FloatPoint(a.x() + b.width(), a.y() + b.height()); } +inline FloatPoint operator+(const FloatPoint& a, const FloatPoint& b) +{ + return FloatPoint(a.x() + b.x(), a.y() + b.y()); +} + inline FloatSize operator-(const FloatPoint& a, const FloatPoint& b) { return FloatSize(a.x() - b.x(), a.y() - b.y()); diff --git a/WebCore/platform/graphics/Font.cpp b/WebCore/platform/graphics/Font.cpp index 0351f7b..61f5707 100644 --- a/WebCore/platform/graphics/Font.cpp +++ b/WebCore/platform/graphics/Font.cpp @@ -72,7 +72,7 @@ Font::Font(const FontDescription& fd, short letterSpacing, short wordSpacing) { } -Font::Font(const FontPlatformData& fontData, bool isPrinterFont) +Font::Font(const FontPlatformData& fontData, bool isPrinterFont, FontSmoothingMode fontSmoothingMode) : m_fontList(FontFallbackList::create()) , m_letterSpacing(0) , m_wordSpacing(0) @@ -80,6 +80,7 @@ Font::Font(const FontPlatformData& fontData, bool isPrinterFont) , m_needsTranscoding(fontTranscoder().needsTranscoding(family().family().string())) { m_fontDescription.setUsePrinterFont(isPrinterFont); + m_fontDescription.setFontSmoothing(fontSmoothingMode); m_fontList->setPlatformFont(fontData); } diff --git a/WebCore/platform/graphics/Font.h b/WebCore/platform/graphics/Font.h index ecfde98..d6cf140 100644 --- a/WebCore/platform/graphics/Font.h +++ b/WebCore/platform/graphics/Font.h @@ -76,7 +76,7 @@ public: Font(); Font(const FontDescription&, short letterSpacing, short wordSpacing); // This constructor is only used if the platform wants to start with a native font. - Font(const FontPlatformData&, bool isPrinting); + Font(const FontPlatformData&, bool isPrinting, FontSmoothingMode = AutoSmoothing); ~Font(); Font(const Font&); @@ -135,7 +135,7 @@ public: float xHeight() const { return primaryFont()->xHeight(); } unsigned unitsPerEm() const { return primaryFont()->unitsPerEm(); } int spaceWidth() const { return (int)ceilf(primaryFont()->adjustedSpaceWidth() + m_letterSpacing); } - int tabWidth() const { return 8 * spaceWidth(); } + float tabWidth(const SimpleFontData& fontData) const { return 8 * ceilf(fontData.adjustedSpaceWidth() + letterSpacing()); } const SimpleFontData* primaryFont() const; const FontData* fontDataAt(unsigned) const; diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h index 882362f..28388f4 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.h +++ b/WebCore/platform/graphics/GraphicsContext3D.h @@ -68,8 +68,13 @@ typedef int Platform3DObject; const Platform3DObject NullPlatform3DObject = 0; #endif +#if PLATFORM(CG) +#include <CoreGraphics/CGContext.h> +#endif + namespace WebCore { class WebGLActiveInfo; + class ArrayBuffer; class ArrayBufferView; class WebGLBuffer; class Uint8Array; @@ -551,7 +556,9 @@ namespace WebCore { void blendFuncSeparate(unsigned long srcRGB, unsigned long dstRGB, unsigned long srcAlpha, unsigned long dstAlpha); void bufferData(unsigned long target, int size, unsigned long usage); + void bufferData(unsigned long target, ArrayBuffer* data, unsigned long usage); void bufferData(unsigned long target, ArrayBufferView* data, unsigned long usage); + void bufferSubData(unsigned long target, long offset, ArrayBuffer* data); void bufferSubData(unsigned long target, long offset, ArrayBufferView* data); unsigned long checkFramebufferStatus(unsigned long target); @@ -707,7 +714,14 @@ namespace WebCore { void viewport(long x, long y, unsigned long width, unsigned long height); void reshape(int width, int height); - + +#if PLATFORM(CG) + void paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, + int canvasWidth, int canvasHeight, CGContextRef context); +#endif + + void paintRenderingResultsToCanvas(WebGLRenderingContext* context); + // Helpers for notification about paint events void beginPaint(WebGLRenderingContext* context); void endPaint(); diff --git a/WebCore/platform/graphics/GraphicsLayer.h b/WebCore/platform/graphics/GraphicsLayer.h index 8fcebce..a5819f4 100644 --- a/WebCore/platform/graphics/GraphicsLayer.h +++ b/WebCore/platform/graphics/GraphicsLayer.h @@ -298,10 +298,11 @@ public: virtual void setContentsToImage(Image*) { } virtual void setContentsToMedia(PlatformLayer*) { } // video or plug-in virtual void setContentsBackgroundColor(const Color&) { } - #if ENABLE(3D_CANVAS) virtual void setContentsToWebGL(PlatformLayer*) { } #endif + virtual bool hasContentsLayer() const { return false; } + // Callback from the underlying graphics system to draw layer contents. void paintGraphicsLayerContents(GraphicsContext&, const IntRect& clip); // Callback from the underlying graphics system when the layer has been displayed @@ -351,6 +352,8 @@ public: // pointers for the layers and timing data will be included in the returned string. String layerTreeAsText(LayerTreeAsTextBehavior = LayerTreeAsTextBehaviorNormal) const; + bool usingTiledLayer() const { return m_usingTiledLayer; } + protected: typedef Vector<TransformOperation::OperationType> TransformOperationList; diff --git a/WebCore/platform/graphics/ImageBuffer.h b/WebCore/platform/graphics/ImageBuffer.h index 9f9ba7e..cb5d63f 100644 --- a/WebCore/platform/graphics/ImageBuffer.h +++ b/WebCore/platform/graphics/ImageBuffer.h @@ -74,6 +74,11 @@ namespace WebCore { GraphicsContext* context() const; Image* image() const; +#if PLATFORM(QT) + Image* imageForRendering() const; +#else + Image* imageForRendering() const { return image(); } +#endif void clearImage() { m_image.clear(); } diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp index 3915713..9290dfe 100644 --- a/WebCore/platform/graphics/MediaPlayer.cpp +++ b/WebCore/platform/graphics/MediaPlayer.cpp @@ -130,6 +130,7 @@ public: #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) virtual void deliverNotification(MediaPlayerProxyNotificationType) { } virtual void setMediaPlayerProxy(WebMediaPlayerProxy*) { } + virtual void setControls(bool) { } #endif virtual bool hasSingleSecurityOrigin() const { return true; } @@ -563,6 +564,21 @@ void MediaPlayer::setMediaPlayerProxy(WebMediaPlayerProxy* proxy) m_playerProxy = proxy; m_private->setMediaPlayerProxy(proxy); } + +void MediaPlayer::setControls(bool controls) +{ + m_private->setControls(controls); +} + +void MediaPlayer::enterFullscreen() +{ + m_private->enterFullscreen(); +} + +void MediaPlayer::exitFullscreen() +{ + m_private->exitFullscreen(); +} #endif #if USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/MediaPlayer.h b/WebCore/platform/graphics/MediaPlayer.h index 87f8fb4..dea5100 100644 --- a/WebCore/platform/graphics/MediaPlayer.h +++ b/WebCore/platform/graphics/MediaPlayer.h @@ -55,6 +55,7 @@ class QTMovieVisualContext; namespace WebCore { class GStreamerGWorld; +class MediaPlayerPrivateInterface; // Structure that will hold every native // types supported by the current media player. @@ -67,6 +68,7 @@ struct PlatformMedia { QTMovieGWorldType, QTMovieVisualContextType, GStreamerGWorldType, + ChromiumMediaPlayerType, } type; union { @@ -74,6 +76,7 @@ struct PlatformMedia { QTMovieGWorld* qtMovieGWorld; QTMovieVisualContext* qtMovieVisualContext; GStreamerGWorld* gstreamerGWorld; + MediaPlayerPrivateInterface* chromiumMediaPlayer; } media; }; @@ -85,7 +88,6 @@ class GraphicsContext; class IntRect; class IntSize; class MediaPlayer; -class MediaPlayerPrivateInterface; class String; class TimeRanges; @@ -256,6 +258,9 @@ public: #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) void deliverNotification(MediaPlayerProxyNotificationType notification); void setMediaPlayerProxy(WebMediaPlayerProxy* proxy); + void setControls(bool); + void enterFullscreen(); + void exitFullscreen(); #endif #if USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/MediaPlayerPrivate.h b/WebCore/platform/graphics/MediaPlayerPrivate.h index 16ff543..40aeacb 100644 --- a/WebCore/platform/graphics/MediaPlayerPrivate.h +++ b/WebCore/platform/graphics/MediaPlayerPrivate.h @@ -107,6 +107,9 @@ public: #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) virtual void deliverNotification(MediaPlayerProxyNotificationType) = 0; virtual void setMediaPlayerProxy(WebMediaPlayerProxy*) = 0; + virtual void setControls(bool) { } + virtual void enterFullscreen() { } + virtual void exitFullscreen() { } #endif #if USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/Path.h b/WebCore/platform/graphics/Path.h index b69670f..f2ae2df 100644 --- a/WebCore/platform/graphics/Path.h +++ b/WebCore/platform/graphics/Path.h @@ -124,6 +124,7 @@ namespace WebCore { // Gets the current point of the current path, which is conceptually the final point reached by the path so far. // Note the Path can be empty (isEmpty() == true) and still have a current point. bool hasCurrentPoint() const; + FloatPoint currentPoint() const; void moveTo(const FloatPoint&); void addLineTo(const FloatPoint&); diff --git a/WebCore/platform/graphics/WidthIterator.cpp b/WebCore/platform/graphics/WidthIterator.cpp index 827cd10..ef047e8 100644 --- a/WebCore/platform/graphics/WidthIterator.cpp +++ b/WebCore/platform/graphics/WidthIterator.cpp @@ -84,7 +84,10 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer) bool rtl = m_run.rtl(); bool hasExtraSpacing = (m_font->letterSpacing() || m_font->wordSpacing() || m_padding) && !m_run.spacingDisabled(); - float runWidthSoFar = m_runWidthSoFar; + float widthSinceLastRounding = m_runWidthSoFar; + m_runWidthSoFar = floorf(m_runWidthSoFar); + widthSinceLastRounding -= m_runWidthSoFar; + float lastRoundingWidth = m_finalRoundingWidth; FloatRect bounds; @@ -130,8 +133,8 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer) // Now that we have a glyph and font data, get its width. float width; if (c == '\t' && m_run.allowTabs()) { - float tabWidth = m_font->tabWidth(); - width = tabWidth - fmodf(m_run.xPos() + runWidthSoFar, tabWidth); + float tabWidth = m_font->tabWidth(*fontData); + width = tabWidth - fmodf(m_run.xPos() + m_runWidthSoFar + widthSinceLastRounding, tabWidth); } else { width = fontData->widthForGlyph(glyph); @@ -216,11 +219,13 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer) // width so that the total run width will be on an integer boundary. if ((m_run.applyWordRounding() && currentCharacter < m_run.length() && Font::isRoundingHackCharacter(*cp)) || (m_run.applyRunRounding() && currentCharacter >= m_end)) { - float totalWidth = runWidthSoFar + width; - width += ceilf(totalWidth) - totalWidth; - } - - runWidthSoFar += width; + float totalWidth = widthSinceLastRounding + width; + widthSinceLastRounding = ceilf(totalWidth); + width += widthSinceLastRounding - totalWidth; + m_runWidthSoFar += widthSinceLastRounding; + widthSinceLastRounding = 0; + } else + widthSinceLastRounding += width; if (glyphBuffer) glyphBuffer->add(glyph, fontData, (rtl ? oldWidth + lastRoundingWidth : width)); @@ -235,7 +240,7 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer) } m_currentCharacter = currentCharacter; - m_runWidthSoFar = runWidthSoFar; + m_runWidthSoFar += widthSinceLastRounding; m_finalRoundingWidth = lastRoundingWidth; } diff --git a/WebCore/platform/graphics/android/ImageBufferAndroid.cpp b/WebCore/platform/graphics/android/ImageBufferAndroid.cpp index 60e2c1c..082af3e 100644 --- a/WebCore/platform/graphics/android/ImageBufferAndroid.cpp +++ b/WebCore/platform/graphics/android/ImageBufferAndroid.cpp @@ -29,8 +29,8 @@ #include "Base64.h" #include "BitmapImage.h" #include "ImageData.h" -#include "android_graphics.h" #include "GraphicsContext.h" +#include "NotImplemented.h" #include "PlatformGraphicsContext.h" #include "SkBitmapRef.h" #include "SkCanvas.h" @@ -39,6 +39,7 @@ #include "SkImageEncoder.h" #include "SkStream.h" #include "SkUnPreMultiply.h" +#include "android_graphics.h" using namespace std; @@ -228,4 +229,9 @@ String ImageBuffer::toDataURL(const String&, const double*) const return String::format("data:image/png;base64,%s", base64EncodedData.data()); } +void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookupTable) +{ + notImplemented(); +} + } diff --git a/WebCore/platform/graphics/android/PathAndroid.cpp b/WebCore/platform/graphics/android/PathAndroid.cpp index f7f6b19..13bd888 100644 --- a/WebCore/platform/graphics/android/PathAndroid.cpp +++ b/WebCore/platform/graphics/android/PathAndroid.cpp @@ -75,6 +75,13 @@ bool Path::hasCurrentPoint() const return m_path->getPoints(0, 0) > 0; } +FloatPoint Path::currentPoint() const +{ + // FIXME: Return current point of subpath. See b/2869593 + float quietNaN = std::numeric_limits<float>::quiet_NaN(); + return FloatPoint(quietNaN, quietNaN); +} + bool Path::contains(const FloatPoint& point, WindRule rule) const { SkRegion rgn, clip; diff --git a/WebCore/platform/graphics/cairo/FontCairo.cpp b/WebCore/platform/graphics/cairo/FontCairo.cpp index 93051cb..9217a81 100644 --- a/WebCore/platform/graphics/cairo/FontCairo.cpp +++ b/WebCore/platform/graphics/cairo/FontCairo.cpp @@ -73,8 +73,8 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons FloatSize shadowSize; float shadowBlur = 0; Color shadowColor; - bool hasShadow = context->textDrawingMode() == cTextFill && - context->getShadow(shadowSize, shadowBlur, shadowColor); + bool hasShadow = context->textDrawingMode() & cTextFill + && context->getShadow(shadowSize, shadowBlur, shadowColor); // TODO: Blur support if (hasShadow) { diff --git a/WebCore/platform/graphics/cairo/PathCairo.cpp b/WebCore/platform/graphics/cairo/PathCairo.cpp index 91cecd3..d880626 100644 --- a/WebCore/platform/graphics/cairo/PathCairo.cpp +++ b/WebCore/platform/graphics/cairo/PathCairo.cpp @@ -86,6 +86,15 @@ bool Path::hasCurrentPoint() const return !isEmpty(); } +FloatPoint Path::currentPoint() const +{ + // FIXME: Is this the correct way? + double x; + double y; + cairo_get_current_point(platformPath()->m_cr, &x, &y); + return FloatPoint(x, y); +} + void Path::translate(const FloatSize& p) { cairo_t* cr = platformPath()->m_cr; diff --git a/WebCore/platform/graphics/cg/ColorCG.cpp b/WebCore/platform/graphics/cg/ColorCG.cpp index e514fa3..9257642 100644 --- a/WebCore/platform/graphics/cg/ColorCG.cpp +++ b/WebCore/platform/graphics/cg/ColorCG.cpp @@ -73,10 +73,14 @@ Color::Color(CGColorRef color) CGColorRef createCGColor(const Color& c) { CGColorRef color = NULL; +#ifdef OBSOLETE_COLORSYNC_API CMProfileRef prof = NULL; CMGetSystemProfile(&prof); - RetainPtr<CGColorSpaceRef> rgbSpace(AdoptCF, CGColorSpaceCreateWithPlatformColorSpace(prof)); +#else + ColorSyncProfileRef prof = ColorSyncProfileCreateWithDisplayID(0); + RetainPtr<CGColorSpaceRef> rgbSpace(AdoptCF, CGColorSpaceCreateWithPlatformColorSpace(const_cast<void*>(reinterpret_cast<const void*>(prof)))); +#endif if (rgbSpace) { CGFloat components[4] = { static_cast<CGFloat>(c.red()) / 255, static_cast<CGFloat>(c.green()) / 255, @@ -84,7 +88,12 @@ CGColorRef createCGColor(const Color& c) color = CGColorCreate(rgbSpace.get(), components); } +#ifdef OBSOLETE_COLORSYNC_API CMCloseProfile(prof); +#else + if (prof) + CFRelease(prof); +#endif return color; } diff --git a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp index 9f0f353..8af3d0e 100644 --- a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp +++ b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp @@ -36,6 +36,8 @@ #include <CoreGraphics/CGContext.h> #include <CoreGraphics/CGImage.h> +#include <wtf/RetainPtr.h> + namespace WebCore { bool GraphicsContext3D::getImageData(Image* image, @@ -104,6 +106,41 @@ bool GraphicsContext3D::getImageData(Image* image, format, type, neededAlphaOp, outputVector.data()); } +void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, CGContextRef context) +{ + if (!imagePixels || imageWidth <= 0 || imageHeight <= 0 || canvasWidth <= 0 || canvasHeight <= 0 || !context) + return; + int rowBytes = imageWidth * 4; + RetainPtr<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(0, imagePixels, rowBytes * imageHeight, 0); + RetainPtr<CGColorSpaceRef> colorSpace = CGColorSpaceCreateDeviceRGB(); + RetainPtr<CGImageRef> cgImage = CGImageCreate(imageWidth, + imageHeight, + 8, + 32, + rowBytes, + colorSpace.get(), + kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, + dataProvider.get(), + 0, + false, + kCGRenderingIntentDefault); + // CSS styling may cause the canvas's content to be resized on + // the page. Go back to the Canvas to figure out the correct + // width and height to draw. + CGRect rect = CGRectMake(0, 0, + canvasWidth, + canvasHeight); + // We want to completely overwrite the previous frame's + // rendering results. + CGContextSaveGState(context); + CGContextSetBlendMode(context, + kCGBlendModeCopy); + CGContextSetInterpolationQuality(context, + kCGInterpolationNone); + CGContextDrawImage(context, + rect, cgImage.get()); + CGContextRestoreGState(context); +} } // namespace WebCore diff --git a/WebCore/platform/graphics/cg/PathCG.cpp b/WebCore/platform/graphics/cg/PathCG.cpp index eb196d9..90d4b8a 100644 --- a/WebCore/platform/graphics/cg/PathCG.cpp +++ b/WebCore/platform/graphics/cg/PathCG.cpp @@ -213,8 +213,7 @@ void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius) void Path::closeSubpath() { - if (!CGPathIsEmpty(m_path)) // to silence a warning when trying to close an empty path - CGPathCloseSubpath(m_path); + CGPathCloseSubpath(m_path); } void Path::addArc(const FloatPoint& p, float r, float sa, float ea, bool clockwise) @@ -249,6 +248,11 @@ bool Path::hasCurrentPoint() const { return !isEmpty(); } + +FloatPoint Path::currentPoint() const +{ + return CGPathGetCurrentPoint(m_path); +} static void CGPathToCFStringApplierFunction(void* info, const CGPathElement *element) { diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp index dda10b7..9b54732 100644 --- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp @@ -43,7 +43,8 @@ namespace WebCore { static SkPaint::Hinting skiaHinting = SkPaint::kNormal_Hinting; -static bool isSkiaAntiAlias = true, isSkiaSubpixelGlyphs; +static bool isSkiaAntiAlias = true; +static bool isSkiaSubpixelGlyphs = false; void FontPlatformData::setHinting(SkPaint::Hinting hinting) { diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp index 9b65346..a01a17f 100644 --- a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp @@ -363,9 +363,30 @@ void GraphicsLayerChromium::setContentsToWebGL(PlatformLayer* platformLayer) } #endif -void GraphicsLayerChromium::setContentsToVideo(PlatformLayer* videoLayer) +void GraphicsLayerChromium::setContentsToMedia(PlatformLayer* layer) { - // FIXME: Implement + bool childrenChanged = false; + if (layer) { + if (!m_contentsLayer.get() || m_contentsLayerPurpose != ContentsLayerForVideo) { + setupContentsLayer(layer); + m_contentsLayer = layer; + m_contentsLayerPurpose = ContentsLayerForVideo; + childrenChanged = true; + } + layer->setOwner(this); + layer->setNeedsDisplay(); + updateContentsRect(); + } else { + if (m_contentsLayer) { + childrenChanged = true; + + // The old contents layer will be removed via updateSublayerList. + m_contentsLayer = 0; + } + } + + if (childrenChanged) + updateSublayerList(); } void GraphicsLayerChromium::setGeometryOrientation(CompositingCoordinatesOrientation orientation) diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h index ccd02eb..cd5e479 100644 --- a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h +++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h @@ -85,7 +85,7 @@ public: virtual void setContentsRect(const IntRect&); virtual void setContentsToImage(Image*); - virtual void setContentsToVideo(PlatformLayer*); + virtual void setContentsToMedia(PlatformLayer*); virtual void setContentsToWebGL(PlatformLayer*); virtual PlatformLayer* platformLayer() const; diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index 9ac506c..b071385 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -37,7 +37,6 @@ #include "GLES2Context.h" #include "LayerChromium.h" #include "NotImplemented.h" -#include "Page.h" #include "TransformLayerChromium.h" #include "WebGLLayerChromium.h" #if PLATFORM(SKIA) @@ -190,24 +189,24 @@ ShaderProgram::ShaderProgram() { } -PassOwnPtr<LayerRendererChromium> LayerRendererChromium::create(Page* page) +PassOwnPtr<LayerRendererChromium> LayerRendererChromium::create(PassOwnPtr<GLES2Context> gles2Context) { - return new LayerRendererChromium(page); + return new LayerRendererChromium(gles2Context); } -LayerRendererChromium::LayerRendererChromium(Page* page) +LayerRendererChromium::LayerRendererChromium(PassOwnPtr<GLES2Context> gles2Context) : m_rootLayer(0) , m_needsDisplay(false) , m_positionLocation(0) , m_texCoordLocation(1) - , m_page(page) , m_rootLayerTextureWidth(0) , m_rootLayerTextureHeight(0) , m_scrollPosition(IntPoint(-1, -1)) , m_currentShaderProgramType(NumShaderProgramTypes) + , m_gles2Context(gles2Context) { m_quadVboIds[Vertices] = m_quadVboIds[LayerElements] = 0; - m_hardwareCompositing = (initGL() && initializeSharedGLObjects()); + m_hardwareCompositing = (m_gles2Context && initializeSharedGLObjects()); } LayerRendererChromium::~LayerRendererChromium() @@ -645,16 +644,6 @@ bool LayerRendererChromium::makeContextCurrent() return m_gles2Context->makeCurrent(); } -bool LayerRendererChromium::initGL() -{ - m_gles2Context = GLES2Context::createOnscreen(m_page); - - if (!m_gles2Context) - return false; - - return true; -} - void LayerRendererChromium::bindCommonAttribLocations(ShaderProgramType program) { unsigned programId = m_shaderPrograms[program].m_shaderProgramId; diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/WebCore/platform/graphics/chromium/LayerRendererChromium.h index dc7ea70..3b89dc6 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.h +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.h @@ -45,7 +45,6 @@ namespace WebCore { class GLES2Context; -class Page; class ShaderProgram { public: @@ -60,9 +59,9 @@ public: // Class that handles drawing of composited render layers using GL. class LayerRendererChromium : public Noncopyable { public: - static PassOwnPtr<LayerRendererChromium> create(Page* page); + static PassOwnPtr<LayerRendererChromium> create(PassOwnPtr<GLES2Context> gles2Context); - LayerRendererChromium(Page* page); + LayerRendererChromium(PassOwnPtr<GLES2Context> gles2Context); ~LayerRendererChromium(); // Updates the contents of the root layer that fall inside the updateRect and recomposites @@ -105,7 +104,6 @@ private: enum VboIds { Vertices, LayerElements }; // These are here only temporarily and should be removed once we switch over to GGL - bool initGL(); bool makeContextCurrent(); bool initializeSharedGLObjects(); @@ -151,9 +149,6 @@ private: IntSize m_rootLayerCanvasSize; OwnPtr<GLES2Context> m_gles2Context; - - // The WebCore Page that the compositor renders into. - Page* m_page; }; } diff --git a/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp new file mode 100644 index 0000000..5ac0e57 --- /dev/null +++ b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "VideoLayerChromium.h" + +namespace WebCore { + +PassRefPtr<VideoLayerChromium> VideoLayerChromium::create(GraphicsLayerChromium* owner) +{ + return adoptRef(new VideoLayerChromium(owner)); +} + +VideoLayerChromium::VideoLayerChromium(GraphicsLayerChromium* owner) + : LayerChromium(owner) +{ +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/chromium/VideoLayerChromium.h b/WebCore/platform/graphics/chromium/VideoLayerChromium.h new file mode 100644 index 0000000..1fa8009 --- /dev/null +++ b/WebCore/platform/graphics/chromium/VideoLayerChromium.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef VideoLayerChromium_h +#define VideoLayerChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerChromium.h" + +namespace WebCore { + +// A Layer that contains a Video element. +class VideoLayerChromium : public LayerChromium { +public: + static PassRefPtr<VideoLayerChromium> create(GraphicsLayerChromium* owner = 0); + virtual bool drawsContent() { return true; } + +private: + VideoLayerChromium(GraphicsLayerChromium* owner); +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/WebCore/platform/graphics/haiku/PathHaiku.cpp b/WebCore/platform/graphics/haiku/PathHaiku.cpp index d8b6932..c5b8c98 100644 --- a/WebCore/platform/graphics/haiku/PathHaiku.cpp +++ b/WebCore/platform/graphics/haiku/PathHaiku.cpp @@ -65,6 +65,14 @@ bool Path::hasCurrentPoint() const return !isEmpty(); } +FloatPoint Path::currentPoint() const +{ + // FIXME: implement safe way to return current point of subpath. + notImplemented(); + float quietNaN = std::numeric_limits<float>::quiet_NaN(); + return FloatPoint(quietNaN, quietNaN); +} + bool Path::contains(const FloatPoint& point, WindRule rule) const { return m_path->Contains(point); diff --git a/WebCore/platform/graphics/mac/ComplexTextController.cpp b/WebCore/platform/graphics/mac/ComplexTextController.cpp index 61c9a59..da381f2 100644 --- a/WebCore/platform/graphics/mac/ComplexTextController.cpp +++ b/WebCore/platform/graphics/mac/ComplexTextController.cpp @@ -431,6 +431,7 @@ void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer) void ComplexTextController::adjustGlyphsAndAdvances() { + CGFloat widthSinceLastRounding = 0; size_t runCount = m_complexTextRuns.size(); for (size_t r = 0; r < runCount; ++r) { ComplexTextRun& complexTextRun = *m_complexTextRuns[r]; @@ -473,8 +474,8 @@ void ComplexTextController::adjustGlyphsAndAdvances() CGSize advance = treatAsSpace ? CGSizeMake(fontData->spaceWidth(), advances[i].height) : advances[i]; if (ch == '\t' && m_run.allowTabs()) { - float tabWidth = m_font.tabWidth(); - advance.width = tabWidth - fmodf(m_run.xPos() + m_totalWidth, tabWidth); + float tabWidth = m_font.tabWidth(*fontData); + advance.width = tabWidth - fmodf(m_run.xPos() + m_totalWidth + widthSinceLastRounding, tabWidth); } else if (ch == zeroWidthSpace || Font::treatAsZeroWidthSpace(ch) && !treatAsSpace) { advance.width = 0; glyph = fontData->spaceGlyph(); @@ -532,21 +533,23 @@ void ComplexTextController::adjustGlyphsAndAdvances() // Check to see if the next character is a "rounding hack character", if so, adjust the // width so that the total run width will be on an integer boundary. if (m_run.applyWordRounding() && !lastGlyph && Font::isRoundingHackCharacter(nextCh) || m_run.applyRunRounding() && lastGlyph) { - CGFloat totalWidth = m_totalWidth + advance.width; - CGFloat extraWidth = ceilCGFloat(totalWidth) - totalWidth; + CGFloat totalWidth = widthSinceLastRounding + advance.width; + widthSinceLastRounding = ceilCGFloat(totalWidth); + CGFloat extraWidth = widthSinceLastRounding - totalWidth; if (m_run.ltr()) advance.width += extraWidth; else { - m_totalWidth += extraWidth; if (m_lastRoundingGlyph) m_adjustedAdvances[m_lastRoundingGlyph - 1].width += extraWidth; else m_finalRoundingWidth = extraWidth; m_lastRoundingGlyph = m_adjustedAdvances.size() + 1; } - } + m_totalWidth += widthSinceLastRounding; + widthSinceLastRounding = 0; + } else + widthSinceLastRounding += advance.width; - m_totalWidth += advance.width; advance.height *= -1; m_adjustedAdvances.append(advance); m_adjustedGlyphs.append(glyph); @@ -565,6 +568,7 @@ void ComplexTextController::adjustGlyphsAndAdvances() if (!isMonotonic) complexTextRun.setIsNonMonotonic(); } + m_totalWidth += widthSinceLastRounding; } } // namespace WebCore diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm index 961ec45..30c3b8e 100644 --- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm +++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm @@ -34,14 +34,18 @@ #include "ImageBuffer.h" #include "NotImplemented.h" #include "WebGLActiveInfo.h" +#include "ArrayBuffer.h" #include "ArrayBufferView.h" #include "WebGLBuffer.h" #include "Float32Array.h" #include "WebGLFramebuffer.h" +#include "GraphicsContext.h" +#include "HTMLCanvasElement.h" #include "Int32Array.h" #include "WebGLLayer.h" #include "WebGLProgram.h" #include "WebGLRenderbuffer.h" +#include "WebGLRenderingContext.h" #include "WebGLShader.h" #include "WebGLTexture.h" #include "Uint8Array.h" @@ -236,6 +240,54 @@ void GraphicsContext3D::makeContextCurrent() CGLSetCurrentContext(m_contextObj); } +void GraphicsContext3D::paintRenderingResultsToCanvas(WebGLRenderingContext* context) +{ + HTMLCanvasElement* canvas = context->canvas(); + ImageBuffer* imageBuffer = canvas->buffer(); + + int rowBytes = m_currentWidth * 4; + int totalBytes = rowBytes * m_currentHeight; + + OwnArrayPtr<unsigned char> pixels(new unsigned char[totalBytes]); + if (!pixels) + return; + + CGLSetCurrentContext(m_contextObj); + + bool mustRestoreFBO = false; + if (m_attrs.antialias) { + ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); + ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); + ::glBlitFramebufferEXT(0, 0, m_currentWidth, m_currentHeight, 0, 0, m_currentWidth, m_currentHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + mustRestoreFBO = true; + } else { + if (m_boundFBO != m_fbo) { + mustRestoreFBO = true; + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + } + } + + GLint packAlignment = 4; + bool mustRestorePackAlignment = false; + ::glGetIntegerv(GL_PACK_ALIGNMENT, &packAlignment); + if (packAlignment > 4) { + ::glPixelStorei(GL_PACK_ALIGNMENT, 4); + mustRestorePackAlignment = true; + } + + ::glReadPixels(0, 0, m_currentWidth, m_currentHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels.get()); + + if (mustRestorePackAlignment) + ::glPixelStorei(GL_PACK_ALIGNMENT, packAlignment); + + if (mustRestoreFBO) + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); + + paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight, + canvas->width(), canvas->height(), imageBuffer->context()->platformContext()); +} + void GraphicsContext3D::beginPaint(WebGLRenderingContext* context) { UNUSED_PARAM(context); @@ -494,6 +546,16 @@ void GraphicsContext3D::bufferData(unsigned long target, int size, unsigned long ensureContext(m_contextObj); ::glBufferData(target, size, 0, usage); } + +void GraphicsContext3D::bufferData(unsigned long target, ArrayBuffer* array, unsigned long usage) +{ + if (!array || !array->byteLength()) + return; + + ensureContext(m_contextObj); + ::glBufferData(target, array->byteLength(), array->data(), usage); +} + void GraphicsContext3D::bufferData(unsigned long target, ArrayBufferView* array, unsigned long usage) { if (!array || !array->length()) @@ -503,6 +565,15 @@ void GraphicsContext3D::bufferData(unsigned long target, ArrayBufferView* array, ::glBufferData(target, array->byteLength(), array->baseAddress(), usage); } +void GraphicsContext3D::bufferSubData(unsigned long target, long offset, ArrayBuffer* array) +{ + if (!array || !array->byteLength()) + return; + + ensureContext(m_contextObj); + ::glBufferSubData(target, offset, array->byteLength(), array->data()); +} + void GraphicsContext3D::bufferSubData(unsigned long target, long offset, ArrayBufferView* array) { if (!array || !array->length()) @@ -1216,6 +1287,10 @@ void GraphicsContext3D::getIntegerv(unsigned long pname, int* value) // Need to emulate IMPLEMENTATION_COLOR_READ_FORMAT/TYPE for GL. Any valid // combination should work, but GL_RGB/GL_UNSIGNED_BYTE might be the most // useful for desktop WebGL users. + // Need to emulate MAX_FRAGMENT/VERTEX_UNIFORM_VECTORS and MAX_VARYING_VECTORS + // because desktop GL's corresponding queries return the number of components + // whereas GLES2 return the number of vectors (each vector has 4 components). + // Therefore, the value returned by desktop GL needs to be divided by 4. ensureContext(m_contextObj); switch (pname) { case IMPLEMENTATION_COLOR_READ_FORMAT: @@ -1224,6 +1299,18 @@ void GraphicsContext3D::getIntegerv(unsigned long pname, int* value) case IMPLEMENTATION_COLOR_READ_TYPE: *value = GL_UNSIGNED_BYTE; break; + case MAX_FRAGMENT_UNIFORM_VECTORS: + ::glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, value); + *value /= 4; + break; + case MAX_VERTEX_UNIFORM_VECTORS: + ::glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, value); + *value /= 4; + break; + case MAX_VARYING_VECTORS: + ::glGetIntegerv(GL_MAX_VARYING_FLOATS, value); + *value /= 4; + break; default: ::glGetIntegerv(pname, value); } diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.h b/WebCore/platform/graphics/mac/GraphicsLayerCA.h index 7d78dee..80c822c 100644 --- a/WebCore/platform/graphics/mac/GraphicsLayerCA.h +++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.h @@ -106,6 +106,7 @@ public: #if ENABLE(3D_CANVAS) virtual void setContentsToWebGL(PlatformLayer*); #endif + virtual bool hasContentsLayer() const { return m_contentsLayer; } virtual PlatformLayer* platformLayer() const; diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm index 43b3f3e..9f1ac83 100644 --- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm +++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm @@ -1057,11 +1057,11 @@ void GraphicsLayerCA::updateSublayerList() void GraphicsLayerCA::updateLayerPosition() { - // FIXME: if constrained the size, the position will be wrong. Fixing this is not trivial. + FloatSize usedSize = m_usingTiledLayer ? constrainedSize() : m_size; // Position is offset on the layer by the layer anchor point. - CGPoint posPoint = CGPointMake(m_position.x() + m_anchorPoint.x() * m_size.width(), - m_position.y() + m_anchorPoint.y() * m_size.height()); + CGPoint posPoint = CGPointMake(m_position.x() + m_anchorPoint.x() * usedSize.width(), + m_position.y() + m_anchorPoint.y() * usedSize.height()); [primaryLayer() setPosition:posPoint]; @@ -2271,8 +2271,6 @@ void GraphicsLayerCA::updateContentsTransform() contentsTransform = CGAffineTransformTranslate(contentsTransform, 0, -[m_layer.get() bounds].size.height); [m_layer.get() setContentsTransform:contentsTransform]; } -#else - ASSERT(contentsOrientation() == CompositingCoordinatesTopDown); #endif } diff --git a/WebCore/platform/graphics/mac/WebLayer.h b/WebCore/platform/graphics/mac/WebLayer.h index af53ae6..3a91f04 100644 --- a/WebCore/platform/graphics/mac/WebLayer.h +++ b/WebCore/platform/graphics/mac/WebLayer.h @@ -53,12 +53,12 @@ namespace WebCore { { WebCore::GraphicsLayer* m_layerOwner; } - -// Class method allows us to share implementation across TiledLayerMac and WebLayer -+ (void)drawContents:(WebCore::GraphicsLayer*)layerContents ofLayer:(CALayer*)layer intoContext:(CGContextRef)context; - @end +// Functions allows us to share implementation across WebTiledLayer and WebLayer +void drawLayerContents(CGContextRef, CALayer *, WebCore::GraphicsLayer*); +void setLayerNeedsDisplayInRect(CALayer *, WebCore::GraphicsLayer*, CGRect); + #endif // USE(ACCELERATED_COMPOSITING) #endif // WebLayer_h diff --git a/WebCore/platform/graphics/mac/WebLayer.mm b/WebCore/platform/graphics/mac/WebLayer.mm index 0c9925e..9bb8212 100644 --- a/WebCore/platform/graphics/mac/WebLayer.mm +++ b/WebCore/platform/graphics/mac/WebLayer.mm @@ -31,6 +31,7 @@ #import "GraphicsContext.h" #import "GraphicsLayer.h" +#import <objc/objc-runtime.h> #import <QuartzCore/QuartzCore.h> #import <wtf/UnusedParam.h> @@ -38,7 +39,7 @@ using namespace WebCore; @implementation WebLayer -+ (void)drawContents:(WebCore::GraphicsLayer*)layerContents ofLayer:(CALayer*)layer intoContext:(CGContextRef)context +void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::GraphicsLayer* layerContents) { if (!layerContents) return; @@ -110,6 +111,34 @@ using namespace WebCore; CGContextRestoreGState(context); } +void setLayerNeedsDisplayInRect(CALayer *layer, WebCore::GraphicsLayer* layerContents, CGRect rect) +{ + if (layerContents && layerContents->client() && layerContents->drawsContent()) { + struct objc_super layerSuper = { layer, class_getSuperclass(object_getClass(layer)) }; +#if defined(BUILDING_ON_LEOPARD) + rect = CGRectApplyAffineTransform(rect, [layer contentsTransform]); +#else + if (layerContents->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesBottomUp) + rect.origin.y = [layer bounds].size.height - rect.origin.y - rect.size.height; +#endif + objc_msgSendSuper(&layerSuper, @selector(setNeedsDisplayInRect:), rect); + +#ifndef NDEBUG + if (layerContents->showRepaintCounter()) { + CGRect bounds = [layer bounds]; + CGRect indicatorRect = CGRectMake(bounds.origin.x, bounds.origin.y, 46, 25); +#if defined(BUILDING_ON_LEOPARD) + indicatorRect = CGRectApplyAffineTransform(indicatorRect, [layer contentsTransform]); +#else + if (layerContents->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesBottomUp) + indicatorRect.origin.y = [layer bounds].size.height - indicatorRect.origin.y - indicatorRect.size.height; +#endif + objc_msgSendSuper(&layerSuper, @selector(setNeedsDisplayInRect:), indicatorRect); + } +#endif + } +} + // Disable default animations - (id<CAAction>)actionForKey:(NSString *)key { @@ -134,23 +163,7 @@ using namespace WebCore; - (void)setNeedsDisplayInRect:(CGRect)dirtyRect { - if (m_layerOwner && m_layerOwner->client() && m_layerOwner->drawsContent()) { -#if defined(BUILDING_ON_LEOPARD) - dirtyRect = CGRectApplyAffineTransform(dirtyRect, [self contentsTransform]); -#endif - [super setNeedsDisplayInRect:dirtyRect]; - -#ifndef NDEBUG - if (m_layerOwner->showRepaintCounter()) { - CGRect bounds = [self bounds]; - CGRect indicatorRect = CGRectMake(bounds.origin.x, bounds.origin.y, 46, 25); -#if defined(BUILDING_ON_LEOPARD) - indicatorRect = CGRectApplyAffineTransform(indicatorRect, [self contentsTransform]); -#endif - [super setNeedsDisplayInRect:indicatorRect]; - } -#endif - } + setLayerNeedsDisplayInRect(self, m_layerOwner, dirtyRect); } - (void)display @@ -162,7 +175,7 @@ using namespace WebCore; - (void)drawInContext:(CGContextRef)context { - [WebLayer drawContents:m_layerOwner ofLayer:self intoContext:context]; + drawLayerContents(context, self, m_layerOwner); } @end // implementation WebLayer diff --git a/WebCore/platform/graphics/mac/WebTiledLayer.mm b/WebCore/platform/graphics/mac/WebTiledLayer.mm index 97ba233..72128ad 100644 --- a/WebCore/platform/graphics/mac/WebTiledLayer.mm +++ b/WebCore/platform/graphics/mac/WebTiledLayer.mm @@ -73,23 +73,7 @@ using namespace WebCore; - (void)setNeedsDisplayInRect:(CGRect)dirtyRect { - if (m_layerOwner && m_layerOwner->client() && m_layerOwner->drawsContent()) { -#if defined(BUILDING_ON_LEOPARD) - dirtyRect = CGRectApplyAffineTransform(dirtyRect, [self contentsTransform]); -#endif - [super setNeedsDisplayInRect:dirtyRect]; - -#ifndef NDEBUG - if (m_layerOwner->showRepaintCounter()) { - CGRect bounds = [self bounds]; - CGRect indicatorRect = CGRectMake(bounds.origin.x, bounds.origin.y, 46, 25); -#if defined(BUILDING_ON_LEOPARD) - indicatorRect = CGRectApplyAffineTransform(indicatorRect, [self contentsTransform]); -#endif - [super setNeedsDisplayInRect:indicatorRect]; - } -#endif - } + setLayerNeedsDisplayInRect(self, m_layerOwner, dirtyRect); } - (void)display @@ -99,9 +83,9 @@ using namespace WebCore; m_layerOwner->didDisplay(self); } -- (void)drawInContext:(CGContextRef)ctx +- (void)drawInContext:(CGContextRef)context { - [WebLayer drawContents:m_layerOwner ofLayer:self intoContext:ctx]; + drawLayerContents(context, self, m_layerOwner); } @end // implementation WebTiledLayer diff --git a/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp b/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp index 12ae09d..7f4547d 100644 --- a/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp +++ b/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp @@ -70,8 +70,8 @@ struct TableDirectoryEntry { BigEndianULong length; }; -#if !PLATFORM(CG) -// Fixed type is not defined on non-CG platforms. |version| in sfntHeader +#if !PLATFORM(CG) || !defined(COREGRAPHICS_INCLUDES_CORESERVICES_HEADER) +// Fixed type is not defined on non-CG and Windows platforms. |version| in sfntHeader // and headTable and |fontRevision| in headTable are of Fixed, but they're // not actually refered to anywhere. Therefore, we just have to match // the size (4 bytes). For the definition of Fixed type, see diff --git a/WebCore/platform/graphics/openvg/PathOpenVG.cpp b/WebCore/platform/graphics/openvg/PathOpenVG.cpp index 7e67036..e74ea57 100644 --- a/WebCore/platform/graphics/openvg/PathOpenVG.cpp +++ b/WebCore/platform/graphics/openvg/PathOpenVG.cpp @@ -123,6 +123,13 @@ Path& Path::operator=(const Path& other) return *this; } +FloatPoint Path::currentPoint() const +{ + // FIXME: is this the way to return the current point of the subpath? + return m_currentPoint; +} + + bool Path::contains(const FloatPoint& point, WindRule rule) const { notImplemented(); diff --git a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp index 002765f..311d3a3 100644 --- a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp @@ -521,6 +521,15 @@ void GraphicsContext3D::makeContextCurrent() void GraphicsContext3D::beginPaint(WebGLRenderingContext* context) { + paintRenderingResultsToCanvas(); +} + +void GraphicsContext3D::endPaint() +{ +} + +void GraphicsContext3D::paintRenderingResultsToCanvas(WebGLRenderingContext* context) +{ m_internal->m_glWidget->makeCurrent(); HTMLCanvasElement* canvas = context->canvas(); ImageBuffer* imageBuffer = canvas->buffer(); @@ -528,10 +537,6 @@ void GraphicsContext3D::beginPaint(WebGLRenderingContext* context) paint(painter, QRect(QPoint(0, 0), QSize(m_currentWidth, m_currentHeight))); } -void GraphicsContext3D::endPaint() -{ -} - void GraphicsContext3D::paint(QPainter* painter, const QRect& rect) const { #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index 913a764..a828070 100644 --- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -358,7 +358,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) StrokeStyle style = strokeStyle(); Color color = strokeColor(); - if (style == NoStroke || !color.alpha()) + if (style == NoStroke) return; float width = strokeThickness(); @@ -467,7 +467,7 @@ void GraphicsContext::drawEllipse(const IntRect& rect) void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan) { - if (paintingDisabled() || strokeStyle() == NoStroke || strokeThickness() <= 0.0f || !strokeColor().alpha()) + if (paintingDisabled() || strokeStyle() == NoStroke || strokeThickness() <= 0.0f) return; QPainter* p = m_data->p(); @@ -567,23 +567,20 @@ void GraphicsContext::fillPath() return; QPainter* p = m_data->p(); - QPainterPath path = m_data->currentPath; + QPainterPath& path = m_data->currentPath; // Avoid detaching the QPainterPath path.setFillRule(toQtFillRule(fillRule())); - if (m_common->state.fillPattern || m_common->state.fillGradient || fillColor().alpha()) { - drawFilledShadowPath(this, p, path); - if (m_common->state.fillPattern) { - AffineTransform affine; - p->fillPath(path, QBrush(m_common->state.fillPattern->createPlatformPattern(affine))); - } else if (m_common->state.fillGradient) { - QBrush brush(*m_common->state.fillGradient->platformGradient()); - brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform()); - p->fillPath(path, brush); - } else { - if (fillColor().alpha()) - p->fillPath(path, p->brush()); - } - } + drawFilledShadowPath(this, p, path); + if (m_common->state.fillPattern) { + AffineTransform affine; + p->fillPath(path, QBrush(m_common->state.fillPattern->createPlatformPattern(affine))); + } else if (m_common->state.fillGradient) { + QBrush brush(*m_common->state.fillGradient->platformGradient()); + brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform()); + p->fillPath(path, brush); + } else + p->fillPath(path, p->brush()); + m_data->currentPath = QPainterPath(); } @@ -594,37 +591,33 @@ void GraphicsContext::strokePath() QPainter* p = m_data->p(); QPen pen(p->pen()); - QPainterPath path = m_data->currentPath; + QPainterPath& path = m_data->currentPath; // Avoid detaching the QPainterPath path.setFillRule(toQtFillRule(fillRule())); - if (m_common->state.strokePattern || m_common->state.strokeGradient || strokeColor().alpha()) { - FloatSize shadowSize; - float shadowBlur; - Color shadowColor; - if (getShadow(shadowSize, shadowBlur, shadowColor)) { - QTransform t(p->worldTransform()); - p->translate(shadowSize.width(), shadowSize.height()); - QPen shadowPen(pen); - shadowPen.setColor(shadowColor); - p->strokePath(path, shadowPen); - p->setWorldTransform(t); - } - if (m_common->state.strokePattern) { - AffineTransform affine; - pen.setBrush(QBrush(m_common->state.strokePattern->createPlatformPattern(affine))); - p->setPen(pen); - p->strokePath(path, pen); - } else if (m_common->state.strokeGradient) { - QBrush brush(*m_common->state.strokeGradient->platformGradient()); - brush.setTransform(m_common->state.strokeGradient->gradientSpaceTransform()); - pen.setBrush(brush); - p->setPen(pen); - p->strokePath(path, pen); - } else { - if (strokeColor().alpha()) - p->strokePath(path, pen); - } + FloatSize shadowSize; + float shadowBlur; + Color shadowColor; + if (getShadow(shadowSize, shadowBlur, shadowColor)) { + QTransform t(p->worldTransform()); + p->translate(shadowSize.width(), shadowSize.height()); + QPen shadowPen(pen); + shadowPen.setColor(shadowColor); + p->strokePath(path, shadowPen); + p->setWorldTransform(t); } + if (m_common->state.strokePattern) { + AffineTransform affine; + pen.setBrush(QBrush(m_common->state.strokePattern->createPlatformPattern(affine))); + p->setPen(pen); + p->strokePath(path, pen); + } else if (m_common->state.strokeGradient) { + QBrush brush(*m_common->state.strokeGradient->platformGradient()); + brush.setTransform(m_common->state.strokeGradient->gradientSpaceTransform()); + pen.setBrush(brush); + p->setPen(pen); + p->strokePath(path, pen); + } else + p->strokePath(path, pen); m_data->currentPath = QPainterPath(); } @@ -713,28 +706,63 @@ void GraphicsContext::fillRect(const FloatRect& rect) return; QPainter* p = m_data->p(); + FloatRect normalizedRect = rect.normalized(); - if (m_common->state.fillPattern || m_common->state.fillGradient || fillColor().alpha()) { - if (m_common->state.shadowColor.isValid()) - drawBorderlessRectShadow(this, p, rect); - if (m_common->state.fillPattern) { - AffineTransform affine; - FloatRect rectM(rect); - QBrush brush(m_common->state.fillPattern->createPlatformPattern(affine)); - QPixmap* image = m_common->state.fillPattern->tileImage()->nativeImageForCurrentFrame(); - - drawRepeatPattern(p, image, rect, m_common->state.fillPattern->repeatX(), m_common->state.fillPattern->repeatY()); - } else if (m_common->state.fillGradient) { - QBrush brush(*m_common->state.fillGradient->platformGradient()); - brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform()); - p->fillRect(rect, brush); - } else { - if (fillColor().alpha()) - p->fillRect(rect, p->brush()); + FloatSize shadowSize; + float shadowBlur; + Color shadowColor; + bool hasShadow = getShadow(shadowSize, shadowBlur, shadowColor); + FloatRect shadowDestRect; + QImage* shadowImage = 0; + QPainter* pShadow = 0; + + if (hasShadow) { + shadowImage = new QImage(roundedIntSize(normalizedRect.size()), QImage::Format_ARGB32_Premultiplied); + pShadow = new QPainter(shadowImage); + shadowDestRect = normalizedRect; + shadowDestRect.move(shadowSize.width(), shadowSize.height()); + + pShadow->setCompositionMode(QPainter::CompositionMode_Source); + pShadow->fillRect(shadowImage->rect(), shadowColor); + pShadow->setCompositionMode(QPainter::CompositionMode_DestinationIn); + } + + if (m_common->state.fillPattern) { + AffineTransform affine; + FloatRect rectM(rect); + QBrush brush(m_common->state.fillPattern->createPlatformPattern(affine)); + QPixmap* image = m_common->state.fillPattern->tileImage()->nativeImageForCurrentFrame(); + + if (hasShadow) { + drawRepeatPattern(pShadow, image, FloatRect(static_cast<QRectF>(shadowImage->rect())), m_common->state.fillPattern->repeatX(), m_common->state.fillPattern->repeatY()); + pShadow->end(); + p->drawImage(shadowDestRect, *shadowImage, shadowImage->rect()); + } + drawRepeatPattern(p, image, normalizedRect, m_common->state.fillPattern->repeatX(), m_common->state.fillPattern->repeatY()); + } else if (m_common->state.fillGradient) { + QBrush brush(*m_common->state.fillGradient->platformGradient()); + brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform()); + + if (hasShadow) { + pShadow->fillRect(shadowImage->rect(), brush); + pShadow->end(); + p->drawImage(shadowDestRect, *shadowImage, shadowImage->rect()); } + p->fillRect(normalizedRect, brush); + } else { + if (hasShadow) { + pShadow->fillRect(shadowImage->rect(), p->brush()); + pShadow->end(); + p->drawImage(shadowDestRect, *shadowImage, shadowImage->rect()); + } + p->fillRect(normalizedRect, p->brush()); } + + delete shadowImage; + delete pShadow; } + void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace) { if (paintingDisabled() || !color.isValid()) @@ -749,7 +777,7 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace) { - if (paintingDisabled() || !color.isValid() || !color.alpha()) + if (paintingDisabled() || !color.isValid()) return; Path path = Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight); @@ -1015,7 +1043,8 @@ void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset) pen.setDashPattern(pattern); pen.setDashOffset(dashOffset); - } + } else + pen.setStyle(Qt::SolidLine); p->setPen(pen); } diff --git a/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/WebCore/platform/graphics/qt/ImageBufferQt.cpp index a546def..b4ca617 100644 --- a/WebCore/platform/graphics/qt/ImageBufferQt.cpp +++ b/WebCore/platform/graphics/qt/ImageBufferQt.cpp @@ -98,6 +98,14 @@ GraphicsContext* ImageBuffer::context() const return m_context.get(); } +Image* ImageBuffer::imageForRendering() const +{ + if (!m_image) + m_image = StillImage::createForRendering(&m_data.m_pixmap); + + return m_image.get(); +} + Image* ImageBuffer::image() const { if (!m_image) { @@ -178,8 +186,13 @@ PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& i unsigned destBytesPerRow = 4 * rect.width(); unsigned char* destRows = data + desty * destBytesPerRow + destx * 4; for (int y = 0; y < numRows; ++y) { +#if QT_VERSION >= 0x040700 + const quint32* scanLine = reinterpret_cast<const quint32*>(image.constScanLine(y + originy)); +#else + quint32* scanLine = reinterpret_cast<quint32*>(image.scanLine(y + originy)); +#endif for (int x = 0; x < numColumns; x++) { - QRgb value = image.pixel(x + originx, y + originy); + QRgb value = scanLine[x + originx]; int basex = x * 4; destRows[basex] = qRed(value); diff --git a/WebCore/platform/graphics/qt/ImageQt.cpp b/WebCore/platform/graphics/qt/ImageQt.cpp index dd97873..e0ac574 100644 --- a/WebCore/platform/graphics/qt/ImageQt.cpp +++ b/WebCore/platform/graphics/qt/ImageQt.cpp @@ -180,8 +180,6 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, return; } - IntSize selfSize = size(); - QPainter* painter(ctxt->platformContext()); QPainter::CompositionMode compositionMode = GraphicsContext::toQtCompositionMode(op); @@ -204,7 +202,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, p.setCompositionMode(QPainter::CompositionMode_Source); p.fillRect(shadowImage.rect(), shadowColor); p.setCompositionMode(QPainter::CompositionMode_DestinationIn); - p.drawPixmap(normalizedDst, *image, normalizedSrc); + p.drawPixmap(QRect(0, 0, normalizedDst.width(), normalizedDst.height()), *image, normalizedSrc); p.end(); painter->drawImage(shadowImageRect, shadowImage, normalizedSrc); } diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp index a367212..a8adb31 100644 --- a/WebCore/platform/graphics/qt/PathQt.cpp +++ b/WebCore/platform/graphics/qt/PathQt.cpp @@ -121,15 +121,18 @@ bool Path::contains(const FloatPoint& point, WindRule rule) const return contains; } +static GraphicsContext* scratchContext() +{ + static ImageBuffer* scratch = ImageBuffer::create(IntSize(1, 1)).leakPtr(); + return scratch->context(); +} + bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point) const { ASSERT(applier); - // FIXME: We should try to use a 'shared Context' instead of creating a new ImageBuffer - // on each call. - OwnPtr<ImageBuffer> scratchImage = ImageBuffer::create(IntSize(1, 1)); - GraphicsContext* gc = scratchImage->context(); QPainterPathStroker stroke; + GraphicsContext* gc = scratchContext(); applier->strokeStyle(gc); QPen pen = gc->pen(); @@ -157,10 +160,7 @@ FloatRect Path::boundingRect() const FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) { - // FIXME: We should try to use a 'shared Context' instead of creating a new ImageBuffer - // on each call. - OwnPtr<ImageBuffer> scratchImage = ImageBuffer::create(IntSize(1, 1)); - GraphicsContext* gc = scratchImage->context(); + GraphicsContext* gc = scratchContext(); QPainterPathStroker stroke; if (applier) { applier->strokeStyle(gc); @@ -198,22 +198,8 @@ void Path::addBezierCurveTo(const FloatPoint& cp1, const FloatPoint& cp2, const void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius) { - // Make sure there is a subpath for p1, the behavior depend on the last element of the subpath. - // When the user agent is to ensure there is a subpath for a coordinate (x, y), the user agent must - // check to see if the context has any subpaths, and if it does not, then the user agent must create - // a new subpath with the point (x, y) as its first (and only) point, as if the moveTo() method had been called. - if (!m_path.elementCount()) { - m_path.moveTo(p1); - return; - } - FloatPoint p0(m_path.currentPosition()); - if ((p1.x() == p0.x() && p1.y() == p0.y()) || (p1.x() == p2.x() && p1.y() == p2.y()) || radius == 0.f) { - m_path.lineTo(p1); - return; - } - FloatPoint p1p0((p0.x() - p1.x()), (p0.y() - p1.y())); FloatPoint p1p2((p2.x() - p1.x()), (p2.y() - p1.y())); float p1p0_length = sqrtf(p1p0.x() * p1p0.x() + p1p0.y() * p1p0.y()); @@ -362,6 +348,11 @@ bool Path::hasCurrentPoint() const return !isEmpty(); } +FloatPoint Path::currentPoint() const +{ + return m_path.currentPosition(); +} + String Path::debugString() const { QString ret; diff --git a/WebCore/platform/graphics/qt/StillImageQt.cpp b/WebCore/platform/graphics/qt/StillImageQt.cpp index 4653c58..9c6acab 100644 --- a/WebCore/platform/graphics/qt/StillImageQt.cpp +++ b/WebCore/platform/graphics/qt/StillImageQt.cpp @@ -36,65 +36,65 @@ namespace WebCore { StillImage::StillImage(const QPixmap& pixmap) + : m_pixmap(new QPixmap(pixmap)) + , m_ownsPixmap(true) +{} + +StillImage::StillImage(const QPixmap* pixmap) : m_pixmap(pixmap) + , m_ownsPixmap(false) {} +StillImage::~StillImage() +{ + if (m_ownsPixmap) + delete m_pixmap; +} + IntSize StillImage::size() const { - return IntSize(m_pixmap.width(), m_pixmap.height()); + return IntSize(m_pixmap->width(), m_pixmap->height()); } NativeImagePtr StillImage::nativeImageForCurrentFrame() { - return const_cast<NativeImagePtr>(&m_pixmap); + return const_cast<NativeImagePtr>(m_pixmap); } void StillImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, ColorSpace, CompositeOperator op) { - if (m_pixmap.isNull()) + if (m_pixmap->isNull()) return; - ctxt->save(); - ctxt->setCompositeOperation(op); - // To support width or height is negative - float sx = src.x(); - float sy = src.y(); - float sw = src.width(); - float sh = src.height(); + FloatRect normalizedSrc = src.normalized(); + FloatRect normalizedDst = dst.normalized(); - if (sw < 0) { - sx = sx + sw; - sw = -sw; - } + QPainter* painter = ctxt->platformContext(); + QPainter::CompositionMode oldCompositionMode = painter->compositionMode(); - if (sh < 0) { - sy = sy + sh; - sh = -sh; - } - - float dx = dst.x(); - float dy = dst.y(); - float dw = dst.width(); - float dh = dst.height(); - - if (dw < 0) { - dx = dx + dw; - dw = -dw; - } + ctxt->setCompositeOperation(op); - if (dh < 0) { - dy = dy + dh; - dh = -dh; + FloatSize shadowSize; + float shadowBlur; + Color shadowColor; + if (ctxt->getShadow(shadowSize, shadowBlur, shadowColor)) { + FloatRect shadowImageRect(normalizedDst); + shadowImageRect.move(shadowSize.width(), shadowSize.height()); + + QImage shadowImage(QSize(static_cast<int>(normalizedSrc.width()), static_cast<int>(normalizedSrc.height())), QImage::Format_ARGB32_Premultiplied); + QPainter p(&shadowImage); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(shadowImage.rect(), shadowColor); + p.setCompositionMode(QPainter::CompositionMode_DestinationIn); + p.drawPixmap(QRect(0, 0, normalizedDst.width(), normalizedDst.height()), *m_pixmap, normalizedSrc); + p.end(); + painter->drawImage(shadowImageRect, shadowImage, normalizedSrc); } - FloatRect srcM(sx, sy, sw, sh); - FloatRect dstM(dx, dy, dw, dh); - QPainter* painter(ctxt->platformContext()); - - painter->drawPixmap(dstM, m_pixmap, srcM); - ctxt->restore(); + painter->drawPixmap(normalizedDst, *m_pixmap, normalizedSrc); + painter->setCompositionMode(oldCompositionMode); } } diff --git a/WebCore/platform/graphics/qt/StillImageQt.h b/WebCore/platform/graphics/qt/StillImageQt.h index 7be9136..58071d9 100644 --- a/WebCore/platform/graphics/qt/StillImageQt.h +++ b/WebCore/platform/graphics/qt/StillImageQt.h @@ -39,6 +39,11 @@ namespace WebCore { return adoptRef(new StillImage(pixmap)); } + static PassRefPtr<StillImage> createForRendering(const QPixmap* pixmap) + { + return adoptRef(new StillImage(pixmap)); + } + // FIXME: StillImages are underreporting decoded sizes and will be unable // to prune because these functions are not implemented yet. virtual void destroyDecodedData(bool destroyAll = true) { Q_UNUSED(destroyAll); } @@ -50,8 +55,11 @@ namespace WebCore { private: StillImage(const QPixmap& pixmap); + StillImage(const QPixmap* pixmap); + ~StillImage(); - QPixmap m_pixmap; + const QPixmap* m_pixmap; + bool m_ownsPixmap; }; } diff --git a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp index 912fd12..f8192fe 100644 --- a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp +++ b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp @@ -74,7 +74,10 @@ ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, b // Make the background transparent. It would be nice if this wasn't // required, but the canvas is currently filled with the magic transparency // color. Can we have another way to manage this? - m_data.m_canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); + // + // Avoid drawing on a zero-sized canvas. Skia can't handle it. + if (!size.isZero()) + m_data.m_canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); success = true; } diff --git a/WebCore/platform/graphics/skia/PathSkia.cpp b/WebCore/platform/graphics/skia/PathSkia.cpp index a0d4c79..12241f8 100644 --- a/WebCore/platform/graphics/skia/PathSkia.cpp +++ b/WebCore/platform/graphics/skia/PathSkia.cpp @@ -74,6 +74,13 @@ bool Path::hasCurrentPoint() const return m_path->getPoints(NULL, 0) != 0; } +FloatPoint Path::currentPoint() const +{ + // FIXME: return current point of subpath. + float quietNaN = std::numeric_limits<float>::quiet_NaN(); + return FloatPoint(quietNaN, quietNaN); +} + bool Path::contains(const FloatPoint& point, WindRule rule) const { return SkPathContainsPoint(m_path, point, diff --git a/WebCore/platform/graphics/skia/SkiaUtils.cpp b/WebCore/platform/graphics/skia/SkiaUtils.cpp index 0c6b2d6..b16a344 100644 --- a/WebCore/platform/graphics/skia/SkiaUtils.cpp +++ b/WebCore/platform/graphics/skia/SkiaUtils.cpp @@ -129,10 +129,18 @@ static U8CPU InvScaleByte(U8CPU component, uint32_t scale) SkColor SkPMColorToColor(SkPMColor pm) { - if (0 == pm) + if (!pm) return 0; - unsigned a = SkGetPackedA32(pm); + if (!a) { + // A zero alpha value when there are non-zero R, G, or B channels is an + // invalid premultiplied color (since all channels should have been + // multiplied by 0 if a=0). + SkASSERT(false); + // In production, return 0 to protect against division by zero. + return 0; + } + uint32_t scale = (255 << 16) / a; return SkColorSetARGB(a, diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp index 20d76ef..96ac0c1 100644 --- a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp +++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp @@ -669,7 +669,7 @@ void GraphicsLayerCACF::updateLayerDrawsContent() if (m_drawsContent) m_layer->setNeedsDisplay(); else - m_layer->setContents(nil); + m_layer->setContents(0); updateDebugIndicators(); } diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp index aa7bdd4..e0ecf78 100644 --- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp @@ -46,6 +46,7 @@ #include "StringHash.h" #include "TimeRanges.h" #include "Timer.h" +#include <AssertMacros.h> #include <CoreGraphics/CGContext.h> #include <Wininet.h> #include <wtf/CurrentTime.h> diff --git a/WebCore/platform/graphics/wince/PathWince.cpp b/WebCore/platform/graphics/wince/PathWince.cpp index 00d03b1..747e650 100644 --- a/WebCore/platform/graphics/wince/PathWince.cpp +++ b/WebCore/platform/graphics/wince/PathWince.cpp @@ -160,4 +160,11 @@ bool Path::hasCurrentPoint() const return !isEmpty(); } +FloatPoint Path::currentPoint() const +{ + // FIXME: return current point of subpath. + float quietNaN = std::numeric_limits<float>::quiet_NaN(); + return FloatPoint(quietNaN, quietNaN); +} + } diff --git a/WebCore/platform/graphics/wx/PathWx.cpp b/WebCore/platform/graphics/wx/PathWx.cpp index 2305be0..3006e27 100644 --- a/WebCore/platform/graphics/wx/PathWx.cpp +++ b/WebCore/platform/graphics/wx/PathWx.cpp @@ -245,4 +245,11 @@ bool Path::hasCurrentPoint() const return !isEmpty(); } +FloatPoint Path::currentPoint() const +{ + // FIXME: return current point of subpath. + float quietNaN = std::numeric_limits<float>::quiet_NaN(); + return FloatPoint(quietNaN, quietNaN); +} + } diff --git a/WebCore/platform/gtk/CursorGtk.cpp b/WebCore/platform/gtk/CursorGtk.cpp index 017e486..a535f0c 100644 --- a/WebCore/platform/gtk/CursorGtk.cpp +++ b/WebCore/platform/gtk/CursorGtk.cpp @@ -57,38 +57,38 @@ static GdkCursor* customCursorNew(CustomCursorType cursorType) Cursor::Cursor(const Cursor& other) - : m_impl(other.m_impl) + : m_platformCursor(other.m_platformCursor) { - if (m_impl) - gdk_cursor_ref(m_impl); + if (m_platformCursor) + gdk_cursor_ref(m_platformCursor); } Cursor::Cursor(Image* image, const IntPoint& hotSpot) { IntPoint effectiveHotSpot = determineHotSpot(image, hotSpot); GdkPixbuf* pixbuf = image->getGdkPixbuf(); - m_impl = gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pixbuf, effectiveHotSpot.x(), effectiveHotSpot.y()); + m_platformCursor = gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pixbuf, effectiveHotSpot.x(), effectiveHotSpot.y()); g_object_unref(pixbuf); } Cursor::~Cursor() { - if (m_impl) - gdk_cursor_unref(m_impl); + if (m_platformCursor) + gdk_cursor_unref(m_platformCursor); } Cursor& Cursor::operator=(const Cursor& other) { - gdk_cursor_ref(other.m_impl); - gdk_cursor_unref(m_impl); - m_impl = other.m_impl; + gdk_cursor_ref(other.m_platformCursor); + gdk_cursor_unref(m_platformCursor); + m_platformCursor = other.m_platformCursor; return *this; } Cursor::Cursor(GdkCursor* c) - : m_impl(c) + : m_platformCursor(c) { - m_impl = c; + m_platformCursor = c; // The GdkCursor may be NULL - the default cursor for the window. if (c) diff --git a/WebCore/platform/gtk/FileSystemGtk.cpp b/WebCore/platform/gtk/FileSystemGtk.cpp index 401bd4a..7ad2a39 100644 --- a/WebCore/platform/gtk/FileSystemGtk.cpp +++ b/WebCore/platform/gtk/FileSystemGtk.cpp @@ -24,12 +24,13 @@ #include "GOwnPtr.h" #include "PlatformString.h" -#include <wtf/text/CString.h> +#include <errno.h> +#include <fcntl.h> #include <glib.h> #include <glib/gstdio.h> - #include <unistd.h> +#include <wtf/text/CString.h> namespace WebCore { @@ -233,6 +234,22 @@ CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle) return tempFilePath; } +PlatformFileHandle openFile(const String& path, FileOpenMode mode) +{ + CString fsRep = fileSystemRepresentation(path); + + if (fsRep.isNull()) + return invalidPlatformFileHandle; + + int platformFlag = 0; + if (mode == OpenForRead) + platformFlag |= O_RDONLY; + else if (mode == OpenForWrite) + platformFlag |= (O_WRONLY | O_CREAT | O_TRUNC); + + return g_open(fsRep.data(), platformFlag, 0666); +} + void closeFile(PlatformFileHandle& handle) { if (isHandleValid(handle)) { @@ -255,6 +272,17 @@ int writeToFile(PlatformFileHandle handle, const char* data, int length) return totalBytesWritten; } +int readFromFile(PlatformFileHandle handle, char* data, int length) +{ + do { + int bytesRead = read(handle, data, static_cast<size_t>(length)); + if (bytesRead >= 0) + return bytesRead; + } while (errno == EINTR); + + return -1; +} + bool unloadModule(PlatformModule module) { return g_module_close(module); diff --git a/WebCore/platform/gtk/PasteboardHelper.cpp b/WebCore/platform/gtk/PasteboardHelper.cpp index 111fb4e..2babe91 100644 --- a/WebCore/platform/gtk/PasteboardHelper.cpp +++ b/WebCore/platform/gtk/PasteboardHelper.cpp @@ -296,6 +296,7 @@ void PasteboardHelper::writeClipboardContents(GtkClipboard* clipboard, GClosure* gtk_clipboard_set_with_data(clipboard, table, numberOfTargets, getClipboardContentsCallback, clearClipboardContentsCallback, callback); + gtk_clipboard_set_can_store(clipboard, 0, 0); settingClipboardDataObject = 0; diff --git a/WebCore/platform/gtk/RenderThemeGtk.cpp b/WebCore/platform/gtk/RenderThemeGtk.cpp index b70773e..bc0d147 100644 --- a/WebCore/platform/gtk/RenderThemeGtk.cpp +++ b/WebCore/platform/gtk/RenderThemeGtk.cpp @@ -762,11 +762,12 @@ bool RenderThemeGtk::paintMediaMuteButton(RenderObject* o, const PaintInfo& pain bool RenderThemeGtk::paintMediaPlayButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) { - HTMLMediaElement* mediaElement = getMediaElementFromRenderObject(o); - if (!mediaElement) + Node* node = o->node(); + if (!node) return false; - return paintMediaButton(paintInfo.context, r, mediaElement->canPlay() ? m_playButton.get() : m_pauseButton.get(), m_panelColor, m_mediaIconSize); + MediaControlPlayButtonElement* button = static_cast<MediaControlPlayButtonElement*>(node); + return paintMediaButton(paintInfo.context, r, button->displayType() == MediaPlayButton ? m_playButton.get() : m_pauseButton.get(), m_panelColor, m_mediaIconSize); } bool RenderThemeGtk::paintMediaSeekBackButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) diff --git a/WebCore/platform/haiku/CursorHaiku.cpp b/WebCore/platform/haiku/CursorHaiku.cpp index 21d678a..58833bc 100644 --- a/WebCore/platform/haiku/CursorHaiku.cpp +++ b/WebCore/platform/haiku/CursorHaiku.cpp @@ -34,31 +34,31 @@ namespace WebCore { Cursor::Cursor(PlatformCursor cursor) - : m_impl(cursor) + : m_platformCursor(cursor) { } Cursor::Cursor(const Cursor& other) - : m_impl(0) + : m_platformCursor(0) { *this = other; } Cursor::~Cursor() { - delete m_impl; + delete m_platformCursor; } Cursor::Cursor(Image*, const IntPoint&) - : m_impl(0) + : m_platformCursor(0) { notImplemented(); } Cursor& Cursor::operator=(const Cursor& other) { - delete m_impl; - m_impl = other.m_impl ? new BCursor(*other.m_impl) : 0; + delete m_platformCursor; + m_platformCursor = other.m_platformCursor ? new BCursor(*other.m_platformCursor) : 0; return *this; } diff --git a/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp b/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp index 19363c8..a2e8760 100644 --- a/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp +++ b/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp @@ -36,6 +36,7 @@ #include "Vector.h" #include "SkBitmap.h" +#include "SkUnPreMultiply.h" extern "C" { #include "png.h" @@ -57,6 +58,25 @@ static void convertBetweenBGRAandRGBA(const unsigned char* input, int numberOfPi } } +// Converts BGRA->RGBA and RGBA->BGRA and undoes alpha premultiplication. +static void preMultipliedBGRAtoRGBA(const unsigned char* input, int numberOfPixels, + unsigned char* output) +{ + SkBitmap inputBitmap; + inputBitmap.setConfig(SkBitmap::kARGB_8888_Config, numberOfPixels, 1); + inputBitmap.setPixels(const_cast<unsigned char*>(input)); + for (int x = 0; x < numberOfPixels; x++) { + uint32_t srcPixel = *inputBitmap.getAddr32(x, 0); + SkColor unmultiplied = SkUnPreMultiply::PMColorToColor(srcPixel); + unsigned char* pixelOut = &output[x * 4]; + pixelOut[0] = SkColorGetR(unmultiplied); + pixelOut[1] = SkColorGetG(unmultiplied); + pixelOut[2] = SkColorGetB(unmultiplied); + pixelOut[3] = SkColorGetA(unmultiplied); + } +} + + // Encoder -------------------------------------------------------------------- // // This section of the code is based on nsPNGEncoder.cpp in Mozilla @@ -98,24 +118,12 @@ private: png_info** m_pngInfo; }; -// static -bool PNGImageEncoder::encode(const SkBitmap& image, Vector<unsigned char>* output) -{ - if (image.config() != SkBitmap::kARGB_8888_Config) - return false; // Only support ARGB at 8 bpp now. - - image.lockPixels(); - bool result = PNGImageEncoder::encode(static_cast<unsigned char*>( - image.getPixels()), IntSize(image.width(), image.height()), - image.rowBytes(), output); - image.unlockPixels(); - return result; -} - -// static -bool PNGImageEncoder::encode(const unsigned char* input, const IntSize& size, - int bytesPerRow, - Vector<unsigned char>* output) +static bool encodeImpl(const unsigned char* input, + const IntSize& size, + int bytesPerRow, + Vector<unsigned char>* output, + void (*conversionFunc)(const unsigned char*, int, unsigned char*) + ) { int inputColorComponents = 4; int outputColorComponents = 4; @@ -158,7 +166,7 @@ bool PNGImageEncoder::encode(const unsigned char* input, const IntSize& size, OwnArrayPtr<unsigned char> rowPixels(new unsigned char[imageSize.width() * outputColorComponents]); for (int y = 0; y < imageSize.height(); y ++) { - convertBetweenBGRAandRGBA(&input[y * bytesPerRow], imageSize.width(), rowPixels.get()); + conversionFunc(&input[y * bytesPerRow], imageSize.width(), rowPixels.get()); png_write_row(pngPtr, rowPixels.get()); } @@ -166,4 +174,27 @@ bool PNGImageEncoder::encode(const unsigned char* input, const IntSize& size, return true; } + +// static +bool PNGImageEncoder::encode(const SkBitmap& image, Vector<unsigned char>* output) +{ + if (image.config() != SkBitmap::kARGB_8888_Config) + return false; // Only support ARGB at 8 bpp now. + + image.lockPixels(); + bool result = encodeImpl(static_cast<unsigned char*>( + image.getPixels()), IntSize(image.width(), image.height()), + image.rowBytes(), output, preMultipliedBGRAtoRGBA); + image.unlockPixels(); + return result; +} + +// static +bool PNGImageEncoder::encode(const unsigned char* input, const IntSize& size, + int bytesPerRow, + Vector<unsigned char>* output) +{ + return encodeImpl(input, size, bytesPerRow, output, convertBetweenBGRAandRGBA); +} + } // namespace WebCore diff --git a/WebCore/platform/mac/CursorMac.mm b/WebCore/platform/mac/CursorMac.mm index 8cd54a1..1b4c1b1 100644 --- a/WebCore/platform/mac/CursorMac.mm +++ b/WebCore/platform/mac/CursorMac.mm @@ -28,8 +28,6 @@ #import "BlockExceptions.h" #import "FoundationExtras.h" -#import "Image.h" -#import "IntPoint.h" #import <wtf/StdLibExtras.h> @interface WebCoreCursorBundle : NSObject { } @@ -50,7 +48,7 @@ static NSCursor* createCustomCursor(Image* image, const IntPoint& hotSpot) if (!img) return 0; BEGIN_BLOCK_OBJC_EXCEPTIONS; - return [[NSCursor alloc] initWithImage:img hotSpot:determineHotSpot(image, hotSpot)]; + return [[NSCursor alloc] initWithImage:img hotSpot:hotSpot]; END_BLOCK_OBJC_EXCEPTIONS; return 0; } @@ -76,281 +74,152 @@ static NSCursor* leakNamedCursor(const char* name, int x, int y) return nil; } -Cursor::Cursor(Image* image, const IntPoint& hotSpot) - : m_impl(HardRetainWithNSRelease(createCustomCursor(image, hotSpot))) -{ +void Cursor::ensurePlatformCursor() const +{ + if (m_platformCursor) + return; + + switch (m_type) { + case Cursor::Pointer: + m_platformCursor = HardRetain([NSCursor arrowCursor]); + break; + case Cursor::Cross: + m_platformCursor = HardRetain(leakNamedCursor("crossHairCursor", 11, 11)); + break; + case Cursor::Hand: + m_platformCursor = HardRetain(leakNamedCursor("linkCursor", 6, 1)); + break; + case Cursor::IBeam: + m_platformCursor = HardRetain([NSCursor IBeamCursor]); + break; + case Cursor::Wait: + m_platformCursor = HardRetain(leakNamedCursor("waitCursor", 7, 7)); + break; + case Cursor::Help: + m_platformCursor = HardRetain(leakNamedCursor("helpCursor", 8, 8)); + break; + case Cursor::Move: + case Cursor::MiddlePanning: + m_platformCursor = HardRetain(leakNamedCursor("moveCursor", 7, 7)); + break; + case Cursor::EastResize: + case Cursor::EastPanning: + m_platformCursor = HardRetain(leakNamedCursor("eastResizeCursor", 14, 7)); + break; + case Cursor::NorthResize: + case Cursor::NorthPanning: + m_platformCursor = HardRetain(leakNamedCursor("northResizeCursor", 7, 1)); + break; + case Cursor::NorthEastResize: + case Cursor::NorthEastPanning: + m_platformCursor = HardRetain(leakNamedCursor("northEastResizeCursor", 14, 1)); + break; + case Cursor::NorthWestResize: + case Cursor::NorthWestPanning: + m_platformCursor = HardRetain(leakNamedCursor("northWestResizeCursor", 0, 0)); + break; + case Cursor::SouthResize: + case Cursor::SouthPanning: + m_platformCursor = HardRetain(leakNamedCursor("southResizeCursor", 7, 14)); + break; + case Cursor::SouthEastResize: + case Cursor::SouthEastPanning: + m_platformCursor = HardRetain(leakNamedCursor("southEastResizeCursor", 14, 14)); + break; + case Cursor::SouthWestResize: + case Cursor::SouthWestPanning: + m_platformCursor = HardRetain(leakNamedCursor("southWestResizeCursor", 1, 14)); + break; + case Cursor::WestResize: + m_platformCursor = HardRetain(leakNamedCursor("westResizeCursor", 1, 7)); + break; + case Cursor::NorthSouthResize: + m_platformCursor = HardRetain(leakNamedCursor("northSouthResizeCursor", 7, 7)); + break; + case Cursor::EastWestResize: + case Cursor::WestPanning: + m_platformCursor = HardRetain(leakNamedCursor("eastWestResizeCursor", 7, 7)); + break; + case Cursor::NorthEastSouthWestResize: + m_platformCursor = HardRetain(leakNamedCursor("northEastSouthWestResizeCursor", 7, 7)); + break; + case Cursor::NorthWestSouthEastResize: + m_platformCursor = HardRetain(leakNamedCursor("northWestSouthEastResizeCursor", 7, 7)); + break; + case Cursor::ColumnResize: + m_platformCursor = HardRetain([NSCursor resizeLeftRightCursor]); + break; + case Cursor::RowResize: + m_platformCursor = HardRetain([NSCursor resizeUpDownCursor]); + break; + case Cursor::VerticalText: + m_platformCursor = HardRetain(leakNamedCursor("verticalTextCursor", 7, 7)); + break; + case Cursor::Cell: + m_platformCursor = HardRetain(leakNamedCursor("cellCursor", 7, 7)); + break; + case Cursor::ContextMenu: + m_platformCursor = HardRetain(leakNamedCursor("contextMenuCursor", 3, 2)); + break; + case Cursor::Alias: + m_platformCursor = HardRetain(leakNamedCursor("aliasCursor", 11, 3)); + break; + case Cursor::Progress: + m_platformCursor = HardRetain(leakNamedCursor("progressCursor", 3, 2)); + break; + case Cursor::NoDrop: + m_platformCursor = HardRetain(leakNamedCursor("noDropCursor", 3, 1)); + break; + case Cursor::Copy: + m_platformCursor = HardRetain(leakNamedCursor("copyCursor", 3, 2)); + break; + case Cursor::None: + m_platformCursor = HardRetain(leakNamedCursor("noneCursor", 7, 7)); + break; + case Cursor::NotAllowed: + m_platformCursor = HardRetain(leakNamedCursor("notAllowedCursor", 11, 11)); + break; + case Cursor::ZoomIn: + m_platformCursor = HardRetain(leakNamedCursor("zoomInCursor", 7, 7)); + break; + case Cursor::ZoomOut: + m_platformCursor = HardRetain(leakNamedCursor("zoomOutCursor", 7, 7)); + break; + case Cursor::Grab: + m_platformCursor = HardRetain([NSCursor openHandCursor]); + break; + case Cursor::Grabbing: + m_platformCursor = HardRetain([NSCursor closedHandCursor]); + break; + case Cursor::Custom: + m_platformCursor = HardRetainWithNSRelease(createCustomCursor(m_image.get(), m_hotSpot)); + break; + } } Cursor::Cursor(const Cursor& other) - : m_impl(HardRetain(other.m_impl)) + : m_type(other.m_type) + , m_image(other.m_image) + , m_hotSpot(other.m_hotSpot) + , m_platformCursor(HardRetain(other.m_platformCursor)) { } -Cursor::~Cursor() -{ - HardRelease(m_impl); -} - Cursor& Cursor::operator=(const Cursor& other) { - HardRetain(other.m_impl); - HardRelease(m_impl); - m_impl = other.m_impl; - return *this; -} - -Cursor::Cursor(NSCursor* c) - : m_impl(HardRetain(c)) -{ -} - -const Cursor& pointerCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor arrowCursor])); - return c; -} - -const Cursor& crossCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("crossHairCursor", 11, 11))); - return c; -} - -const Cursor& handCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("linkCursor", 6, 1))); - return c; -} - -const Cursor& moveCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("moveCursor", 7, 7))); - return c; -} - -const Cursor& verticalTextCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("verticalTextCursor", 7, 7))); - return c; -} - -const Cursor& cellCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("cellCursor", 7, 7))); - return c; -} - -const Cursor& contextMenuCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("contextMenuCursor", 3, 2))); - return c; -} - -const Cursor& aliasCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("aliasCursor", 11, 3))); - return c; -} - -const Cursor& zoomInCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("zoomInCursor", 7, 7))); - return c; -} - -const Cursor& zoomOutCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("zoomOutCursor", 7, 7))); - return c; -} - -const Cursor& copyCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("copyCursor", 3, 2))); - return c; -} - -const Cursor& noneCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("noneCursor", 7, 7))); - return c; -} - -const Cursor& progressCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("progressCursor", 3, 2))); - return c; -} - -const Cursor& noDropCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("noDropCursor", 3, 1))); - return c; -} - -const Cursor& notAllowedCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("notAllowedCursor", 11, 11))); - return c; -} - -const Cursor& iBeamCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor IBeamCursor])); - return c; -} - -const Cursor& waitCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("waitCursor", 7, 7))); - return c; -} - -const Cursor& helpCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("helpCursor", 8, 8))); - return c; -} - -const Cursor& eastResizeCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("eastResizeCursor", 14, 7))); - return c; -} - -const Cursor& northResizeCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northResizeCursor", 7, 1))); - return c; -} - -const Cursor& northEastResizeCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northEastResizeCursor", 14, 1))); - return c; -} - -const Cursor& northWestResizeCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northWestResizeCursor", 0, 0))); - return c; -} - -const Cursor& southResizeCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("southResizeCursor", 7, 14))); - return c; -} - -const Cursor& southEastResizeCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("southEastResizeCursor", 14, 14))); - return c; -} - -const Cursor& southWestResizeCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("southWestResizeCursor", 1, 14))); - return c; -} - -const Cursor& westResizeCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("westResizeCursor", 1, 7))); - return c; -} - -const Cursor& northSouthResizeCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northSouthResizeCursor", 7, 7))); - return c; -} - -const Cursor& eastWestResizeCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("eastWestResizeCursor", 7, 7))); - return c; -} - -const Cursor& northEastSouthWestResizeCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northEastSouthWestResizeCursor", 7, 7))); - return c; -} + m_type = other.m_type; + m_image = other.m_image; + m_hotSpot = other.m_hotSpot; -const Cursor& northWestSouthEastResizeCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northWestSouthEastResizeCursor", 7, 7))); - return c; -} - -const Cursor& columnResizeCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor resizeLeftRightCursor])); - return c; -} - -const Cursor& rowResizeCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor resizeUpDownCursor])); - return c; -} - -const Cursor& middlePanningCursor() -{ - return moveCursor(); -} - -const Cursor& eastPanningCursor() -{ - return eastResizeCursor(); -} - -const Cursor& northPanningCursor() -{ - return northResizeCursor(); -} - -const Cursor& northEastPanningCursor() -{ - return northEastResizeCursor(); -} - -const Cursor& northWestPanningCursor() -{ - return northWestResizeCursor(); -} - -const Cursor& southPanningCursor() -{ - return southResizeCursor(); -} - -const Cursor& southEastPanningCursor() -{ - return southEastResizeCursor(); -} - -const Cursor& southWestPanningCursor() -{ - return southWestResizeCursor(); -} - -const Cursor& westPanningCursor() -{ - return westResizeCursor(); -} - -const Cursor& grabCursor() -{ - DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor openHandCursor])); - return c; + HardRetain(other.m_platformCursor); + HardRelease(m_platformCursor); + m_platformCursor = other.m_platformCursor; + return *this; } -const Cursor& grabbingCursor() +Cursor::~Cursor() { - DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor closedHandCursor])); - return c; + HardRelease(m_platformCursor); } -} +} // namespace WebCore diff --git a/WebCore/platform/mac/FileSystemMac.mm b/WebCore/platform/mac/FileSystemMac.mm index 98f85bb..0df3c89 100644 --- a/WebCore/platform/mac/FileSystemMac.mm +++ b/WebCore/platform/mac/FileSystemMac.mm @@ -29,6 +29,7 @@ #import "FileSystem.h" #import "PlatformString.h" +#import <wtf/text/CString.h> namespace WebCore { @@ -37,4 +38,28 @@ String homeDirectoryPath() return NSHomeDirectory(); } +CString openTemporaryFile(const char* prefix, PlatformFileHandle& platformFileHandle) +{ + platformFileHandle = invalidPlatformFileHandle; + + Vector<char> temporaryFilePath(PATH_MAX); + if (!confstr(_CS_DARWIN_USER_TEMP_DIR, temporaryFilePath.data(), temporaryFilePath.size())) + return CString(); + + // Shrink the vector. + temporaryFilePath.shrink(strlen(temporaryFilePath.data())); + ASSERT(temporaryFilePath.last() == '/'); + + // Append the file name. + temporaryFilePath.append(prefix, strlen(prefix)); + temporaryFilePath.append("XXXXXX", 6); + temporaryFilePath.append('\0'); + + platformFileHandle = mkstemp(temporaryFilePath.data()); + if (platformFileHandle == invalidPlatformFileHandle) + return CString(); + + return CString(temporaryFilePath.data()); +} + } // namespace WebCore diff --git a/WebCore/platform/mac/ThemeMac.mm b/WebCore/platform/mac/ThemeMac.mm index 20b662f..c57e8df 100644 --- a/WebCore/platform/mac/ThemeMac.mm +++ b/WebCore/platform/mac/ThemeMac.mm @@ -687,7 +687,7 @@ void ThemeMac::inflateControlPaintRect(ControlPart part, ControlStates states, I break; } case OuterSpinButtonPart: { - static const int stepperMargin[4] = { 0, 0, 0, 0}; + static const int stepperMargin[4] = { 0, 0, 0, 0 }; ControlSize controlSize = controlSizeFromPixelSize(stepperSizes(), zoomedRect.size(), zoomFactor); IntSize zoomedSize = stepperSizes()[controlSize]; zoomedSize.setHeight(zoomedSize.height() * zoomFactor); diff --git a/WebCore/platform/mac/WidgetMac.mm b/WebCore/platform/mac/WidgetMac.mm index 37c9e9f..2598591 100644 --- a/WebCore/platform/mac/WidgetMac.mm +++ b/WebCore/platform/mac/WidgetMac.mm @@ -123,11 +123,12 @@ void Widget::setFocus(bool focused) END_BLOCK_OBJC_EXCEPTIONS; } - void Widget::setCursor(const Cursor& cursor) - { - if ([NSCursor currentCursor] == cursor.impl()) +void Widget::setCursor(const Cursor& cursor) +{ + ScrollView* view = root(); + if (!view) return; - [cursor.impl() set]; + view->hostWindow()->setCursor(cursor); } void Widget::show() diff --git a/WebCore/platform/network/Credential.cpp b/WebCore/platform/network/Credential.cpp index 87cd7ff..4b24403 100644 --- a/WebCore/platform/network/Credential.cpp +++ b/WebCore/platform/network/Credential.cpp @@ -114,7 +114,7 @@ CFArrayRef Credential::certificates() const return m_certificates.get(); } -const CredentialType Credential::type() const +CredentialType Credential::type() const { return m_type; } diff --git a/WebCore/platform/network/Credential.h b/WebCore/platform/network/Credential.h index 199817c..4fb8bfd 100644 --- a/WebCore/platform/network/Credential.h +++ b/WebCore/platform/network/Credential.h @@ -69,7 +69,7 @@ public: #if CERTIFICATE_CREDENTIALS_SUPPORTED SecIdentityRef identity() const; CFArrayRef certificates() const; - const CredentialType type() const; + CredentialType type() const; #endif private: diff --git a/WebCore/platform/network/CredentialStorage.cpp b/WebCore/platform/network/CredentialStorage.cpp index a48af77..14f4086 100644 --- a/WebCore/platform/network/CredentialStorage.cpp +++ b/WebCore/platform/network/CredentialStorage.cpp @@ -106,6 +106,11 @@ Credential CredentialStorage::get(const ProtectionSpace& protectionSpace) return protectionSpaceToCredentialMap().get(protectionSpace); } +void CredentialStorage::remove(const ProtectionSpace& protectionSpace) +{ + protectionSpaceToCredentialMap().remove(protectionSpace); +} + static PathToDefaultProtectionSpaceMap::iterator findDefaultProtectionSpaceForURL(const KURL& url) { ASSERT(url.protocolInHTTPFamily()); diff --git a/WebCore/platform/network/CredentialStorage.h b/WebCore/platform/network/CredentialStorage.h index ff7b5ee..d11384d 100644 --- a/WebCore/platform/network/CredentialStorage.h +++ b/WebCore/platform/network/CredentialStorage.h @@ -37,6 +37,7 @@ public: // WebCore session credential storage. static void set(const Credential&, const ProtectionSpace&, const KURL&); static Credential get(const ProtectionSpace&); + static void remove(const ProtectionSpace&); // OS persistent storage. static Credential getFromPersistentStorage(const ProtectionSpace&); diff --git a/WebCore/platform/network/FormData.cpp b/WebCore/platform/network/FormData.cpp index 9e4a227..80f17da 100644 --- a/WebCore/platform/network/FormData.cpp +++ b/WebCore/platform/network/FormData.cpp @@ -224,7 +224,12 @@ void FormData::appendKeyValuePairItems(const BlobItemList& items, const TextEnco const FileBlobItem* fileItem = value->toFileBlobItem(); if (fileItem) { const String& path = fileItem->path(); + +#if ENABLE(DIRECTORY_UPLOAD) + String fileName = !fileItem->relativePath().isEmpty() ? fileItem->relativePath() : fileItem->name(); +#else String fileName = fileItem->name(); +#endif // Let the application specify a filename if it's going to generate a replacement file for the upload. if (!path.isEmpty()) { diff --git a/WebCore/platform/network/NetworkStateNotifier.h b/WebCore/platform/network/NetworkStateNotifier.h index ade27fd..21d0067 100644 --- a/WebCore/platform/network/NetworkStateNotifier.h +++ b/WebCore/platform/network/NetworkStateNotifier.h @@ -129,7 +129,7 @@ inline NetworkStateNotifier::NetworkStateNotifier() : m_isOnLine(true) #if PLATFORM(ANDROID) // TODO: Upstream to webkit.org - , m_type(Connection::Unknown) + , m_type(Connection::UNKNOWN) #endif , m_networkStateChangedFunction(0) { diff --git a/WebCore/platform/network/ResourceHandle.cpp b/WebCore/platform/network/ResourceHandle.cpp index d3ee3f2..0575523 100644 --- a/WebCore/platform/network/ResourceHandle.cpp +++ b/WebCore/platform/network/ResourceHandle.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,30 +37,28 @@ namespace WebCore { static bool shouldForceContentSniffing; -ResourceHandle::ResourceHandle(const ResourceRequest& request, ResourceHandleClient* client, bool defersLoading, - bool shouldContentSniff) - : d(new ResourceHandleInternal(this, request, client, defersLoading, shouldContentSniff)) +ResourceHandle::ResourceHandle(const ResourceRequest& request, ResourceHandleClient* client, bool defersLoading, bool shouldContentSniff) + : d(new ResourceHandleInternal(this, request, client, defersLoading, shouldContentSniff && shouldContentSniffURL(request.url()))) { + if (!request.url().isValid()) { + scheduleFailure(InvalidURLFailure); + return; + } + + if (!portAllowed(request.url())) { + scheduleFailure(BlockedFailure); + return; + } } PassRefPtr<ResourceHandle> ResourceHandle::create(const ResourceRequest& request, ResourceHandleClient* client, Frame* frame, bool defersLoading, bool shouldContentSniff) { - if (shouldContentSniff) - shouldContentSniff = shouldContentSniffURL(request.url()); - RefPtr<ResourceHandle> newHandle(adoptRef(new ResourceHandle(request, client, defersLoading, shouldContentSniff))); - if (!request.url().isValid()) { - newHandle->scheduleFailure(InvalidURLFailure); + if (newHandle->d->m_scheduledFailureType != NoFailure) return newHandle.release(); - } - if (!portAllowed(request.url())) { - newHandle->scheduleFailure(BlockedFailure); - return newHandle.release(); - } - if (newHandle->start(frame)) return newHandle.release(); @@ -105,9 +103,9 @@ void ResourceHandle::setClient(ResourceHandleClient* client) d->m_client = client; } -const ResourceRequest& ResourceHandle::request() const +ResourceRequest& ResourceHandle::firstRequest() { - return d->m_request; + return d->m_firstRequest; } const String& ResourceHandle::lastHTTPMethod() const @@ -115,6 +113,11 @@ const String& ResourceHandle::lastHTTPMethod() const return d->m_lastHTTPMethod; } +bool ResourceHandle::hasAuthenticationChallenge() const +{ + return !d->m_currentWebChallenge.isNull(); +} + void ResourceHandle::clearAuthentication() { #if PLATFORM(MAC) diff --git a/WebCore/platform/network/ResourceHandle.h b/WebCore/platform/network/ResourceHandle.h index e1c889a..3dc38f8 100644 --- a/WebCore/platform/network/ResourceHandle.h +++ b/WebCore/platform/network/ResourceHandle.h @@ -110,8 +110,8 @@ private: public: // FIXME: should not need the Frame static PassRefPtr<ResourceHandle> create(const ResourceRequest&, ResourceHandleClient*, Frame*, bool defersLoading, bool shouldContentSniff); - static void loadResourceSynchronously(const ResourceRequest&, StoredCredentials, ResourceError&, ResourceResponse&, Vector<char>& data, Frame* frame); + static void prepareForURL(const KURL&); static bool willLoadFromCache(ResourceRequest&, Frame*); static void cacheMetadata(const ResourceResponse&, const Vector<char>&); @@ -187,7 +187,8 @@ public: // Used to work around the fact that you don't get any more NSURLConnection callbacks until you return from the one you're in. static bool loadsBlocked(); - + + bool hasAuthenticationChallenge() const; void clearAuthentication(); void cancel(); @@ -200,8 +201,8 @@ public: // TODO: this needs upstreaming. void pauseLoad(bool); #endif - - const ResourceRequest& request() const; + + ResourceRequest& firstRequest(); const String& lastHTTPMethod() const; void fireFailure(Timer<ResourceHandle>*); @@ -219,6 +220,12 @@ private: virtual void refAuthenticationClient() { ref(); } virtual void derefAuthenticationClient() { deref(); } +#if PLATFORM(MAC) + void createNSURLConnection(id delegate, bool shouldUseCredentialStorage, bool shouldContentSniff); +#elif PLATFORM(CF) + void createCFURLConnection(bool shouldUseCredentialStorage, bool shouldContentSniff); +#endif + friend class ResourceHandleInternal; OwnPtr<ResourceHandleInternal> d; }; diff --git a/WebCore/platform/network/ResourceHandleInternal.h b/WebCore/platform/network/ResourceHandleInternal.h index 92b24cb..7b6e960 100644 --- a/WebCore/platform/network/ResourceHandleInternal.h +++ b/WebCore/platform/network/ResourceHandleInternal.h @@ -83,7 +83,7 @@ namespace WebCore { public: ResourceHandleInternal(ResourceHandle* loader, const ResourceRequest& request, ResourceHandleClient* c, bool defersLoading, bool shouldContentSniff) : m_client(c) - , m_request(request) + , m_firstRequest(request) , m_lastHTTPMethod(request.httpMethod()) , status(0) , m_defersLoading(defersLoading) @@ -136,10 +136,10 @@ namespace WebCore { , m_scheduledFailureType(ResourceHandle::NoFailure) , m_failureTimer(loader, &ResourceHandle::fireFailure) { - const KURL& url = m_request.url(); + const KURL& url = m_firstRequest.url(); m_user = url.user(); m_pass = url.pass(); - m_request.removeCredentials(); + m_firstRequest.removeCredentials(); } ~ResourceHandleInternal(); @@ -147,7 +147,7 @@ namespace WebCore { ResourceHandleClient* client() { return m_client; } ResourceHandleClient* m_client; - ResourceRequest m_request; + ResourceRequest m_firstRequest; String m_lastHTTPMethod; // Suggested credentials for the current redirection step. diff --git a/WebCore/platform/network/ResourceResponseBase.cpp b/WebCore/platform/network/ResourceResponseBase.cpp index 89d31d7..f30344e 100644 --- a/WebCore/platform/network/ResourceResponseBase.cpp +++ b/WebCore/platform/network/ResourceResponseBase.cpp @@ -45,6 +45,7 @@ ResourceResponseBase::ResourceResponseBase() , m_lastModifiedDate(0) , m_wasCached(false) , m_connectionID(0) + , m_connectionReused(false) , m_isNull(true) , m_haveParsedCacheControlHeader(false) , m_haveParsedAgeHeader(false) @@ -72,6 +73,7 @@ ResourceResponseBase::ResourceResponseBase(const KURL& url, const String& mimeTy , m_lastModifiedDate(0) , m_wasCached(false) , m_connectionID(0) + , m_connectionReused(false) , m_isNull(false) , m_haveParsedCacheControlHeader(false) , m_haveParsedAgeHeader(false) @@ -471,6 +473,20 @@ void ResourceResponseBase::setWasCached(bool value) m_wasCached = value; } +bool ResourceResponseBase::connectionReused() const +{ + lazyInit(); + + return m_connectionReused; +} + +void ResourceResponseBase::setConnectionReused(bool connectionReused) +{ + lazyInit(); + + m_connectionReused = connectionReused; +} + unsigned ResourceResponseBase::connectionID() const { lazyInit(); diff --git a/WebCore/platform/network/ResourceResponseBase.h b/WebCore/platform/network/ResourceResponseBase.h index 858a612..65e24ad 100644 --- a/WebCore/platform/network/ResourceResponseBase.h +++ b/WebCore/platform/network/ResourceResponseBase.h @@ -100,6 +100,9 @@ public: unsigned connectionID() const; void setConnectionID(unsigned); + bool connectionReused() const; + void setConnectionReused(bool); + bool wasCached() const; void setWasCached(bool); @@ -136,8 +139,9 @@ protected: String m_httpStatusText; HTTPHeaderMap m_httpHeaderFields; time_t m_lastModifiedDate; - bool m_wasCached; + bool m_wasCached : 1; unsigned m_connectionID; + bool m_connectionReused : 1; RefPtr<ResourceLoadTiming> m_resourceLoadTiming; bool m_isNull : 1; diff --git a/WebCore/platform/network/android/ResourceHandleAndroid.cpp b/WebCore/platform/network/android/ResourceHandleAndroid.cpp index b8bc6da..fbafd6d 100644 --- a/WebCore/platform/network/android/ResourceHandleAndroid.cpp +++ b/WebCore/platform/network/android/ResourceHandleAndroid.cpp @@ -55,7 +55,7 @@ bool ResourceHandle::start(Frame* frame) bool isMainResource = static_cast<void*>(mainLoader) == static_cast<void*>(client()); - PassRefPtr<ResourceLoaderAndroid> loader = ResourceLoaderAndroid::start(this, d->m_request, frame->loader()->client(), isMainResource, false); + PassRefPtr<ResourceLoaderAndroid> loader = ResourceLoaderAndroid::start(this, d->m_firstRequest, frame->loader()->client(), isMainResource, false); if (loader) { d->m_loader = loader; diff --git a/WebCore/platform/network/cf/ResourceErrorCF.cpp b/WebCore/platform/network/cf/ResourceErrorCF.cpp index dacc68b..1eba97e 100644 --- a/WebCore/platform/network/cf/ResourceErrorCF.cpp +++ b/WebCore/platform/network/cf/ResourceErrorCF.cpp @@ -115,7 +115,7 @@ ResourceError::operator CFErrorRef() const { if (m_isNull) { ASSERT(!m_platformError); - return nil; + return 0; } if (!m_platformError) { diff --git a/WebCore/platform/network/cf/ResourceHandleCFNet.cpp b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp index 1139126..419e397 100644 --- a/WebCore/platform/network/cf/ResourceHandleCFNet.cpp +++ b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp @@ -66,36 +66,40 @@ namespace WebCore { static CFStringRef WebCoreSynchronousLoaderRunLoopMode = CFSTR("WebCoreSynchronousLoaderRunLoopMode"); -class WebCoreSynchronousLoader { +class WebCoreSynchronousLoaderClient : public ResourceHandleClient { public: - static RetainPtr<CFDataRef> load(const ResourceRequest&, StoredCredentials, ResourceResponse&, ResourceError&); + static PassOwnPtr<WebCoreSynchronousLoaderClient> create(ResourceResponse& response, ResourceError& error) + { + return adoptPtr(new WebCoreSynchronousLoaderClient(response, error)); + } + + void setAllowStoredCredentials(bool allow) { m_allowStoredCredentials = allow; } + bool isDone() { return m_isDone; } + + CFMutableDataRef data() { return m_data.get(); } private: - WebCoreSynchronousLoader(ResourceResponse& response, ResourceError& error) - : m_isDone(false) + WebCoreSynchronousLoaderClient(ResourceResponse& response, ResourceError& error) + : m_allowStoredCredentials(false) , m_response(response) , m_error(error) + , m_isDone(false) { } - static CFURLRequestRef willSendRequest(CFURLConnectionRef, CFURLRequestRef, CFURLResponseRef, const void* clientInfo); - static void didReceiveResponse(CFURLConnectionRef, CFURLResponseRef, const void* clientInfo); - static void didReceiveData(CFURLConnectionRef, CFDataRef, CFIndex, const void* clientInfo); - static void didFinishLoading(CFURLConnectionRef, const void* clientInfo); - static void didFail(CFURLConnectionRef, CFErrorRef, const void* clientInfo); - static void didReceiveChallenge(CFURLConnectionRef, CFURLAuthChallengeRef, const void* clientInfo); - static Boolean shouldUseCredentialStorage(CFURLConnectionRef, const void* clientInfo); + virtual void willSendRequest(ResourceHandle*, ResourceRequest&, const ResourceResponse& /*redirectResponse*/); + virtual bool shouldUseCredentialStorage(ResourceHandle*); + virtual void didReceiveAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge&); + virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&); + virtual void didReceiveData(ResourceHandle*, const char*, int, int /*lengthReceived*/); + virtual void didFinishLoading(ResourceHandle*); + virtual void didFail(ResourceHandle*, const ResourceError&); - bool m_isDone; - RetainPtr<CFURLRef> m_url; - RetainPtr<CFStringRef> m_user; - RetainPtr<CFStringRef> m_pass; - // Store the preemptively used initial credential so that if we get an authentication challenge, we won't use the same one again. - Credential m_initialCredential; bool m_allowStoredCredentials; ResourceResponse& m_response; RetainPtr<CFMutableDataRef> m_data; ResourceError& m_error; + bool m_isDone; }; static HashSet<String>& allowsAnyHTTPSCertificateHosts() @@ -137,7 +141,7 @@ CFURLRequestRef willSendRequest(CFURLConnectionRef conn, CFURLRequestRef cfReque return cfRequest; } - LOG(Network, "CFNet - willSendRequest(conn=%p, handle=%p) (%s)", conn, handle, handle->request().url().string().utf8().data()); + LOG(Network, "CFNet - willSendRequest(conn=%p, handle=%p) (%s)", conn, handle, handle->firstRequest().url().string().utf8().data()); ResourceRequest request; if (cfRedirectResponse) { @@ -149,11 +153,11 @@ CFURLRequestRef willSendRequest(CFURLConnectionRef conn, CFURLRequestRef cfReque RetainPtr<CFMutableURLRequestRef> mutableRequest(AdoptCF, CFURLRequestCreateMutableCopy(0, cfRequest)); CFURLRequestSetHTTPRequestMethod(mutableRequest.get(), lastHTTPMethod.get()); - FormData* body = handle->request().httpBody(); - if (!equalIgnoringCase(handle->request().httpMethod(), "GET") && body && !body->isEmpty()) + FormData* body = handle->firstRequest().httpBody(); + if (!equalIgnoringCase(handle->firstRequest().httpMethod(), "GET") && body && !body->isEmpty()) WebCore::setHTTPBody(mutableRequest.get(), body); - String originalContentType = handle->request().httpContentType(); + String originalContentType = handle->firstRequest().httpContentType(); RetainPtr<CFStringRef> originalContentTypeCF(AdoptCF, originalContentType.createCFString()); if (!originalContentType.isEmpty()) CFURLRequestSetHTTPHeaderFieldValue(mutableRequest.get(), CFSTR("Content-Type"), originalContentTypeCF.get()); @@ -184,7 +188,7 @@ void didReceiveResponse(CFURLConnectionRef conn, CFURLResponseRef cfResponse, co { ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo)); - LOG(Network, "CFNet - didReceiveResponse(conn=%p, handle=%p) (%s)", conn, handle, handle->request().url().string().utf8().data()); + LOG(Network, "CFNet - didReceiveResponse(conn=%p, handle=%p) (%s)", conn, handle, handle->firstRequest().url().string().utf8().data()); if (!handle->client()) return; @@ -204,7 +208,7 @@ void didReceiveData(CFURLConnectionRef conn, CFDataRef data, CFIndex originalLen const UInt8* bytes = CFDataGetBytePtr(data); CFIndex length = CFDataGetLength(data); - LOG(Network, "CFNet - didReceiveData(conn=%p, handle=%p, bytes=%d) (%s)", conn, handle, length, handle->request().url().string().utf8().data()); + LOG(Network, "CFNet - didReceiveData(conn=%p, handle=%p, bytes=%d) (%s)", conn, handle, length, handle->firstRequest().url().string().utf8().data()); if (handle->client()) handle->client()->didReceiveData(handle, (const char*)bytes, length, originalLength); @@ -222,7 +226,7 @@ static Boolean shouldUseCredentialStorageCallback(CFURLConnectionRef conn, const { ResourceHandle* handle = const_cast<ResourceHandle*>(static_cast<const ResourceHandle*>(clientInfo)); - LOG(Network, "CFNet - shouldUseCredentialStorage(conn=%p, handle=%p) (%s)", conn, handle, handle->request().url().string().utf8().data()); + LOG(Network, "CFNet - shouldUseCredentialStorage(conn=%p, handle=%p) (%s)", conn, handle, handle->firstRequest().url().string().utf8().data()); if (!handle) return false; @@ -234,7 +238,7 @@ void didFinishLoading(CFURLConnectionRef conn, const void* clientInfo) { ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo)); - LOG(Network, "CFNet - didFinishLoading(conn=%p, handle=%p) (%s)", conn, handle, handle->request().url().string().utf8().data()); + LOG(Network, "CFNet - didFinishLoading(conn=%p, handle=%p) (%s)", conn, handle, handle->firstRequest().url().string().utf8().data()); if (handle->client()) handle->client()->didFinishLoading(handle); @@ -244,7 +248,7 @@ void didFail(CFURLConnectionRef conn, CFErrorRef error, const void* clientInfo) { ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo)); - LOG(Network, "CFNet - didFail(conn=%p, handle=%p, error = %p) (%s)", conn, handle, error, handle->request().url().string().utf8().data()); + LOG(Network, "CFNet - didFail(conn=%p, handle=%p, error = %p) (%s)", conn, handle, error, handle->firstRequest().url().string().utf8().data()); if (handle->client()) handle->client()->didFail(handle, ResourceError(error)); @@ -277,7 +281,7 @@ void didReceiveChallenge(CFURLConnectionRef conn, CFURLAuthChallengeRef challeng { ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo)); ASSERT(handle); - LOG(Network, "CFNet - didReceiveChallenge(conn=%p, handle=%p (%s)", conn, handle, handle->request().url().string().utf8().data()); + LOG(Network, "CFNet - didReceiveChallenge(conn=%p, handle=%p (%s)", conn, handle, handle->firstRequest().url().string().utf8().data()); handle->didReceiveAuthenticationChallenge(AuthenticationChallenge(challenge, handle)); } @@ -300,14 +304,14 @@ void addHeadersFromHashMap(CFMutableURLRequestRef request, const HTTPHeaderMap& ResourceHandleInternal::~ResourceHandleInternal() { if (m_connection) { - LOG(Network, "CFNet - Cancelling connection %p (%s)", m_connection, m_request.url().string().utf8().data()); + LOG(Network, "CFNet - Cancelling connection %p (%s)", m_connection, m_firstRequest.url().string().utf8().data()); CFURLConnectionCancel(m_connection.get()); } } ResourceHandle::~ResourceHandle() { - LOG(Network, "CFNet - Destroying job %p (%s)", this, d->m_request.url().string().utf8().data()); + LOG(Network, "CFNet - Destroying job %p (%s)", this, d->m_firstRequest.url().string().utf8().data()); } CFArrayRef arrayFromFormData(const FormData& d) @@ -390,56 +394,60 @@ static CFDictionaryRef createConnectionProperties(bool shouldUseCredentialStorag return propertiesDictionary; } -bool ResourceHandle::start(Frame* frame) +void ResourceHandle::createCFURLConnection(bool shouldUseCredentialStorage, bool shouldContentSniff) { - // If we are no longer attached to a Page, this must be an attempted load from an - // onUnload handler, so let's just block it. - if (!frame->page()) - return false; - - if ((!d->m_user.isEmpty() || !d->m_pass.isEmpty()) && !d->m_request.url().protocolInHTTPFamily()) { + if ((!d->m_user.isEmpty() || !d->m_pass.isEmpty()) && !firstRequest().url().protocolInHTTPFamily()) { // Credentials for ftp can only be passed in URL, the didReceiveAuthenticationChallenge delegate call won't be made. - KURL urlWithCredentials(d->m_request.url()); + KURL urlWithCredentials(firstRequest().url()); urlWithCredentials.setUser(d->m_user); urlWithCredentials.setPass(d->m_pass); - d->m_request.setURL(urlWithCredentials); + firstRequest().setURL(urlWithCredentials); } - bool shouldUseCredentialStorage = !client() || client()->shouldUseCredentialStorage(this); - // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication, // try and reuse the credential preemptively, as allowed by RFC 2617. - if (shouldUseCredentialStorage && d->m_request.url().protocolInHTTPFamily()) { + if (shouldUseCredentialStorage && firstRequest().url().protocolInHTTPFamily()) { if (d->m_user.isEmpty() && d->m_pass.isEmpty()) { // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication, // try and reuse the credential preemptively, as allowed by RFC 2617. - d->m_initialCredential = CredentialStorage::get(d->m_request.url()); + d->m_initialCredential = CredentialStorage::get(firstRequest().url()); } else { // If there is already a protection space known for the URL, update stored credentials before sending a request. // This makes it possible to implement logout by sending an XMLHttpRequest with known incorrect credentials, and aborting it immediately // (so that an authentication dialog doesn't pop up). - CredentialStorage::set(Credential(d->m_user, d->m_pass, CredentialPersistenceNone), d->m_request.url()); + CredentialStorage::set(Credential(d->m_user, d->m_pass, CredentialPersistenceNone), firstRequest().url()); } } if (!d->m_initialCredential.isEmpty()) { String authHeader = "Basic " + encodeBasicAuthorization(d->m_initialCredential.user(), d->m_initialCredential.password()); - d->m_request.addHTTPHeaderField("Authorization", authHeader); + firstRequest().addHTTPHeaderField("Authorization", authHeader); } - RetainPtr<CFURLRequestRef> request(AdoptCF, makeFinalRequest(d->m_request, d->m_shouldContentSniff)); - - CFURLConnectionClient_V3 client = { 3, this, 0, 0, 0, WebCore::willSendRequest, didReceiveResponse, didReceiveData, NULL, didFinishLoading, didFail, willCacheResponse, didReceiveChallenge, didSendBodyData, shouldUseCredentialStorageCallback, 0}; + RetainPtr<CFURLRequestRef> request(AdoptCF, makeFinalRequest(firstRequest(), shouldContentSniff)); + CFURLConnectionClient_V3 client = { 3, this, 0, 0, 0, WebCore::willSendRequest, didReceiveResponse, didReceiveData, 0, didFinishLoading, didFail, willCacheResponse, didReceiveChallenge, didSendBodyData, shouldUseCredentialStorageCallback, 0}; RetainPtr<CFDictionaryRef> connectionProperties(AdoptCF, createConnectionProperties(shouldUseCredentialStorage)); d->m_connection.adoptCF(CFURLConnectionCreateWithProperties(0, request.get(), reinterpret_cast<CFURLConnectionClient*>(&client), connectionProperties.get())); +} + +bool ResourceHandle::start(Frame* frame) +{ + // If we are no longer attached to a Page, this must be an attempted load from an + // onUnload handler, so let's just block it. + if (!frame->page()) + return false; + + bool shouldUseCredentialStorage = !client() || client()->shouldUseCredentialStorage(this); + + createCFURLConnection(shouldUseCredentialStorage, d->m_shouldContentSniff); CFURLConnectionScheduleWithCurrentMessageQueue(d->m_connection.get()); CFURLConnectionScheduleDownloadWithRunLoop(d->m_connection.get(), loaderRunLoop(), kCFRunLoopDefaultMode); CFURLConnectionStart(d->m_connection.get()); - LOG(Network, "CFNet - Starting URL %s (handle=%p, conn=%p)", d->m_request.url().string().utf8().data(), this, d->m_connection); + LOG(Network, "CFNet - Starting URL %s (handle=%p, conn=%p)", firstRequest().url().string().utf8().data(), this, d->m_connection); return true; } @@ -500,7 +508,7 @@ void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChall KURL urlToStore; if (challenge.failureResponse().httpStatusCode() == 401) - urlToStore = d->m_request.url(); + urlToStore = firstRequest().url(); CredentialStorage::set(core(credential.get()), challenge.protectionSpace(), urlToStore); CFURLConnectionUseCredential(d->m_connection.get(), credential.get(), challenge.cfURLAuthChallengeRef()); @@ -510,17 +518,26 @@ void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChall return; } - if (!challenge.previousFailureCount() && (!client() || client()->shouldUseCredentialStorage(this))) { - Credential credential = CredentialStorage::get(challenge.protectionSpace()); - if (!credential.isEmpty() && credential != d->m_initialCredential) { - ASSERT(credential.persistence() == CredentialPersistenceNone); - if (challenge.failureResponse().httpStatusCode() == 401) { - // Store the credential back, possibly adding it as a default for this directory. - CredentialStorage::set(credential, challenge.protectionSpace(), d->m_request.url()); + if (!client() || client()->shouldUseCredentialStorage(this)) { + if (!d->m_initialCredential.isEmpty() || challenge.previousFailureCount()) { + // The stored credential wasn't accepted, stop using it. + // There is a race condition here, since a different credential might have already been stored by another ResourceHandle, + // but the observable effect should be very minor, if any. + CredentialStorage::remove(challenge.protectionSpace()); + } + + if (!challenge.previousFailureCount()) { + Credential credential = CredentialStorage::get(challenge.protectionSpace()); + if (!credential.isEmpty() && credential != d->m_initialCredential) { + ASSERT(credential.persistence() == CredentialPersistenceNone); + if (challenge.failureResponse().httpStatusCode() == 401) { + // Store the credential back, possibly adding it as a default for this directory. + CredentialStorage::set(credential, challenge.protectionSpace(), firstRequest().url()); + } + RetainPtr<CFURLCredentialRef> cfCredential(AdoptCF, createCF(credential)); + CFURLConnectionUseCredential(d->m_connection.get(), cfCredential.get(), challenge.cfURLAuthChallengeRef()); + return; } - RetainPtr<CFURLCredentialRef> cfCredential(AdoptCF, createCF(credential)); - CFURLConnectionUseCredential(d->m_connection.get(), cfCredential.get(), challenge.cfURLAuthChallengeRef()); - return; } } @@ -552,7 +569,7 @@ void ResourceHandle::receivedCredential(const AuthenticationChallenge& challenge KURL urlToStore; if (challenge.failureResponse().httpStatusCode() == 401) - urlToStore = d->m_request.url(); + urlToStore = firstRequest().url(); CredentialStorage::set(webCredential, challenge.protectionSpace(), urlToStore); CFURLConnectionUseCredential(d->m_connection.get(), cfCredential.get(), challenge.cfURLAuthChallengeRef()); @@ -598,12 +615,43 @@ CFURLConnectionRef ResourceHandle::releaseConnectionForDownload() return d->m_connection.releaseRef(); } -void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials storedCredentials, ResourceError& error, ResourceResponse& response, Vector<char>& vector, Frame*) +void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials storedCredentials, ResourceError& error, ResourceResponse& response, Vector<char>& vector, Frame* frame) { + LOG(Network, "ResourceHandle::loadResourceSynchronously:%s allowStoredCredentials:%u", request.url().string().utf8().data(), storedCredentials); + ASSERT(!request.isEmpty()); - RetainPtr<CFDataRef> data = WebCoreSynchronousLoader::load(request, storedCredentials, response, error); + ASSERT(response.isNull()); + ASSERT(error.isNull()); + + OwnPtr<WebCoreSynchronousLoaderClient> client = WebCoreSynchronousLoaderClient::create(response, error); + client->setAllowStoredCredentials(storedCredentials == AllowStoredCredentials); + + RefPtr<ResourceHandle> handle = adoptRef(new ResourceHandle(request, client.get(), false /*defersLoading*/, true /*shouldContentSniff*/)); + + if (handle->d->m_scheduledFailureType != NoFailure) { + error = frame->loader()->blockedError(request); + return; + } + + RetainPtr<CFDictionaryRef> connectionProperties(AdoptCF, createConnectionProperties(storedCredentials == AllowStoredCredentials)); + handle->createCFURLConnection(storedCredentials == AllowStoredCredentials, ResourceHandle::shouldContentSniffURL(request.url())); + + CFURLConnectionScheduleWithRunLoop(handle->connection(), CFRunLoopGetCurrent(), WebCoreSynchronousLoaderRunLoopMode); + CFURLConnectionScheduleDownloadWithRunLoop(handle->connection(), CFRunLoopGetCurrent(), WebCoreSynchronousLoaderRunLoopMode); + CFURLConnectionStart(handle->connection()); + + while (!client->isDone()) + CFRunLoopRunInMode(WebCoreSynchronousLoaderRunLoopMode, UINT_MAX, true); + + CFURLConnectionCancel(handle->connection()); + + if (error.isNull() && response.mimeType().isNull()) + setDefaultMIMEType(response.cfURLResponse()); + + RetainPtr<CFDataRef> data = client->data(); + if (!error.isNull()) { response = ResourceResponse(request.url(), String(), 0, String(), String()); @@ -666,173 +714,51 @@ bool ResourceHandle::willLoadFromCache(ResourceRequest& request, Frame* frame) return cached; } -CFURLRequestRef WebCoreSynchronousLoader::willSendRequest(CFURLConnectionRef, CFURLRequestRef cfRequest, CFURLResponseRef cfRedirectResponse, const void* clientInfo) +void WebCoreSynchronousLoaderClient::willSendRequest(ResourceHandle* handle, ResourceRequest& request, const ResourceResponse& /*redirectResponse*/) { - WebCoreSynchronousLoader* loader = static_cast<WebCoreSynchronousLoader*>(const_cast<void*>(clientInfo)); - // FIXME: This needs to be fixed to follow the redirect correctly even for cross-domain requests. - if (loader->m_url && !protocolHostAndPortAreEqual(loader->m_url.get(), CFURLRequestGetURL(cfRequest))) { + if (!protocolHostAndPortAreEqual(handle->firstRequest().url(), request.url())) { + ASSERT(!m_error); RetainPtr<CFErrorRef> cfError(AdoptCF, CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainCFNetwork, kCFURLErrorBadServerResponse, 0)); - loader->m_error = cfError.get(); - loader->m_isDone = true; - return 0; - } - - loader->m_url = CFURLRequestGetURL(cfRequest); - - if (cfRedirectResponse) { - // Take user/pass out of the URL. - loader->m_user.adoptCF(CFURLCopyUserName(loader->m_url.get())); - loader->m_pass.adoptCF(CFURLCopyPassword(loader->m_url.get())); - if (loader->m_user || loader->m_pass) { - ResourceRequest requestWithoutCredentials = cfRequest; - requestWithoutCredentials.removeCredentials(); - cfRequest = requestWithoutCredentials.cfURLRequest(); - } + m_error = cfError.get(); + m_isDone = true; + request = 0; + return; } - - CFRetain(cfRequest); - return cfRequest; } - -void WebCoreSynchronousLoader::didReceiveResponse(CFURLConnectionRef, CFURLResponseRef cfResponse, const void* clientInfo) +void WebCoreSynchronousLoaderClient::didReceiveResponse(ResourceHandle*, const ResourceResponse& response) { - WebCoreSynchronousLoader* loader = static_cast<WebCoreSynchronousLoader*>(const_cast<void*>(clientInfo)); - - loader->m_response = cfResponse; + m_response = response; } -void WebCoreSynchronousLoader::didReceiveData(CFURLConnectionRef, CFDataRef data, CFIndex originalLength, const void* clientInfo) +void WebCoreSynchronousLoaderClient::didReceiveData(ResourceHandle*, const char* data, int length, int /*lengthReceived*/) { - WebCoreSynchronousLoader* loader = static_cast<WebCoreSynchronousLoader*>(const_cast<void*>(clientInfo)); - - if (!loader->m_data) - loader->m_data.adoptCF(CFDataCreateMutable(kCFAllocatorDefault, 0)); - - const UInt8* bytes = CFDataGetBytePtr(data); - CFIndex length = CFDataGetLength(data); - - CFDataAppendBytes(loader->m_data.get(), bytes, length); + if (!m_data) + m_data.adoptCF(CFDataCreateMutable(kCFAllocatorDefault, 0)); + CFDataAppendBytes(m_data.get(), reinterpret_cast<const UInt8*>(data), length); } -void WebCoreSynchronousLoader::didFinishLoading(CFURLConnectionRef, const void* clientInfo) +void WebCoreSynchronousLoaderClient::didFinishLoading(ResourceHandle*) { - WebCoreSynchronousLoader* loader = static_cast<WebCoreSynchronousLoader*>(const_cast<void*>(clientInfo)); - - loader->m_isDone = true; + m_isDone = true; } -void WebCoreSynchronousLoader::didFail(CFURLConnectionRef, CFErrorRef error, const void* clientInfo) +void WebCoreSynchronousLoaderClient::didFail(ResourceHandle*, const ResourceError& error) { - WebCoreSynchronousLoader* loader = static_cast<WebCoreSynchronousLoader*>(const_cast<void*>(clientInfo)); - - loader->m_error = error; - loader->m_isDone = true; + m_error = error; + m_isDone = true; } -void WebCoreSynchronousLoader::didReceiveChallenge(CFURLConnectionRef conn, CFURLAuthChallengeRef challenge, const void* clientInfo) +void WebCoreSynchronousLoaderClient::didReceiveAuthenticationChallenge(ResourceHandle* handle, const AuthenticationChallenge& challenge) { - WebCoreSynchronousLoader* loader = static_cast<WebCoreSynchronousLoader*>(const_cast<void*>(clientInfo)); - - CFURLResponseRef urlResponse = (CFURLResponseRef)CFURLAuthChallengeGetFailureResponse(challenge); - CFHTTPMessageRef httpResponse = urlResponse ? CFURLResponseGetHTTPResponse(urlResponse) : 0; - - if (loader->m_user && loader->m_pass) { - Credential credential(loader->m_user.get(), loader->m_pass.get(), CredentialPersistenceNone); - RetainPtr<CFURLCredentialRef> cfCredential(AdoptCF, createCF(credential)); - - KURL urlToStore; - if (httpResponse && CFHTTPMessageGetResponseStatusCode(httpResponse) == 401) - urlToStore = loader->m_url.get(); - - CredentialStorage::set(credential, core(CFURLAuthChallengeGetProtectionSpace(challenge)), urlToStore); - - CFURLConnectionUseCredential(conn, cfCredential.get(), challenge); - loader->m_user = 0; - loader->m_pass = 0; - return; - } - if (!CFURLAuthChallengeGetPreviousFailureCount(challenge) && loader->m_allowStoredCredentials) { - Credential credential = CredentialStorage::get(core(CFURLAuthChallengeGetProtectionSpace(challenge))); - if (!credential.isEmpty() && credential != loader->m_initialCredential) { - ASSERT(credential.persistence() == CredentialPersistenceNone); - if (httpResponse && CFHTTPMessageGetResponseStatusCode(httpResponse) == 401) { - // Store the credential back, possibly adding it as a default for this directory. - CredentialStorage::set(credential, core(CFURLAuthChallengeGetProtectionSpace(challenge)), loader->m_url.get()); - } - RetainPtr<CFURLCredentialRef> cfCredential(AdoptCF, createCF(credential)); - CFURLConnectionUseCredential(conn, cfCredential.get(), challenge); - return; - } - } // FIXME: The user should be asked for credentials, as in async case. - CFURLConnectionUseCredential(conn, 0, challenge); + CFURLConnectionUseCredential(handle->connection(), 0, challenge.cfURLAuthChallengeRef()); } -Boolean WebCoreSynchronousLoader::shouldUseCredentialStorage(CFURLConnectionRef, const void* clientInfo) +bool WebCoreSynchronousLoaderClient::shouldUseCredentialStorage(ResourceHandle*) { - WebCoreSynchronousLoader* loader = static_cast<WebCoreSynchronousLoader*>(const_cast<void*>(clientInfo)); - // FIXME: We should ask FrameLoaderClient whether using credential storage is globally forbidden. - return loader->m_allowStoredCredentials; -} - -RetainPtr<CFDataRef> WebCoreSynchronousLoader::load(const ResourceRequest& request, StoredCredentials storedCredentials, ResourceResponse& response, ResourceError& error) -{ - ASSERT(response.isNull()); - ASSERT(error.isNull()); - - WebCoreSynchronousLoader loader(response, error); - - KURL url = request.url(); - - if (url.user().length()) - loader.m_user.adoptCF(url.user().createCFString()); - if (url.pass().length()) - loader.m_pass.adoptCF(url.pass().createCFString()); - loader.m_allowStoredCredentials = (storedCredentials == AllowStoredCredentials); - - // Take user/pass out of the URL. - // Credentials for ftp can only be passed in URL, the didReceiveAuthenticationChallenge delegate call won't be made. - RetainPtr<CFURLRequestRef> cfRequest; - if ((loader.m_user || loader.m_pass) && url.protocolInHTTPFamily()) { - ResourceRequest requestWithoutCredentials(request); - requestWithoutCredentials.removeCredentials(); - cfRequest.adoptCF(makeFinalRequest(requestWithoutCredentials, ResourceHandle::shouldContentSniffURL(requestWithoutCredentials.url()))); - } else { - // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication, - // try and reuse the credential preemptively, as allowed by RFC 2617. - ResourceRequest requestWithInitialCredential(request); - if (loader.m_allowStoredCredentials && url.protocolInHTTPFamily()) - loader.m_initialCredential = CredentialStorage::get(url); - - if (!loader.m_initialCredential.isEmpty()) { - String authHeader = "Basic " + encodeBasicAuthorization(loader.m_initialCredential.user(), loader.m_initialCredential.password()); - requestWithInitialCredential.addHTTPHeaderField("Authorization", authHeader); - } - - cfRequest.adoptCF(makeFinalRequest(requestWithInitialCredential, ResourceHandle::shouldContentSniffURL(requestWithInitialCredential.url()))); - } - - CFURLConnectionClient_V3 client = { 3, &loader, 0, 0, 0, willSendRequest, didReceiveResponse, didReceiveData, 0, didFinishLoading, didFail, 0, didReceiveChallenge, 0, shouldUseCredentialStorage, 0 }; - - RetainPtr<CFDictionaryRef> connectionProperties(AdoptCF, createConnectionProperties(loader.m_allowStoredCredentials)); - - RetainPtr<CFURLConnectionRef> connection(AdoptCF, CFURLConnectionCreateWithProperties(kCFAllocatorDefault, cfRequest.get(), reinterpret_cast<CFURLConnectionClient*>(&client), connectionProperties.get())); - - CFURLConnectionScheduleWithRunLoop(connection.get(), CFRunLoopGetCurrent(), WebCoreSynchronousLoaderRunLoopMode); - CFURLConnectionScheduleDownloadWithRunLoop(connection.get(), CFRunLoopGetCurrent(), WebCoreSynchronousLoaderRunLoopMode); - CFURLConnectionStart(connection.get()); - - while (!loader.m_isDone) - CFRunLoopRunInMode(WebCoreSynchronousLoaderRunLoopMode, UINT_MAX, true); - - CFURLConnectionCancel(connection.get()); - - if (error.isNull() && loader.m_response.mimeType().isNull()) - setDefaultMIMEType(loader.m_response.cfURLResponse()); - - return loader.m_data; + return m_allowStoredCredentials; } } // namespace WebCore diff --git a/WebCore/platform/network/cf/ResourceRequestCFNet.cpp b/WebCore/platform/network/cf/ResourceRequestCFNet.cpp index cc0220e..8e15040 100644 --- a/WebCore/platform/network/cf/ResourceRequestCFNet.cpp +++ b/WebCore/platform/network/cf/ResourceRequestCFNet.cpp @@ -146,6 +146,11 @@ void ResourceRequest::doUpdatePlatformRequest() void ResourceRequest::doUpdateResourceRequest() { + if (!m_cfRequest) { + *this = ResourceRequest(); + return; + } + m_url = CFURLRequestGetURL(m_cfRequest.get()); m_cachePolicy = (ResourceRequestCachePolicy)CFURLRequestGetCachePolicy(m_cfRequest.get()); diff --git a/WebCore/platform/network/curl/FormDataStreamCurl.cpp b/WebCore/platform/network/curl/FormDataStreamCurl.cpp index 0f94d63..e47eb07 100644 --- a/WebCore/platform/network/curl/FormDataStreamCurl.cpp +++ b/WebCore/platform/network/curl/FormDataStreamCurl.cpp @@ -50,8 +50,8 @@ size_t FormDataStream::read(void* ptr, size_t blockSize, size_t numberOfBlocks) return 0; Vector<FormDataElement> elements; - if (m_resourceHandle->request().httpBody()) - elements = m_resourceHandle->request().httpBody()->elements(); + if (m_resourceHandle->firstRequest().httpBody()) + elements = m_resourceHandle->firstRequest().httpBody()->elements(); if (m_formDataElementIndex >= elements.size()) return 0; @@ -104,8 +104,8 @@ size_t FormDataStream::read(void* ptr, size_t blockSize, size_t numberOfBlocks) bool FormDataStream::hasMoreElements() const { Vector<FormDataElement> elements; - if (m_resourceHandle->request().httpBody()) - elements = m_resourceHandle->request().httpBody()->elements(); + if (m_resourceHandle->firstRequest().httpBody()) + elements = m_resourceHandle->firstRequest().httpBody()->elements(); return m_formDataElementIndex < elements.size(); } diff --git a/WebCore/platform/network/curl/ResourceHandleManager.cpp b/WebCore/platform/network/curl/ResourceHandleManager.cpp index c621d5c..ba68351 100644 --- a/WebCore/platform/network/curl/ResourceHandleManager.cpp +++ b/WebCore/platform/network/curl/ResourceHandleManager.cpp @@ -264,14 +264,14 @@ static size_t headerCallback(char* ptr, size_t size, size_t nmemb, void* data) if (httpCode >= 300 && httpCode < 400) { String location = d->m_response.httpHeaderField("location"); if (!location.isEmpty()) { - KURL newURL = KURL(job->request().url(), location); + KURL newURL = KURL(job->firstRequest().url(), location); - ResourceRequest redirectedRequest = job->request(); + ResourceRequest redirectedRequest = job->firstRequest(); redirectedRequest.setURL(newURL); if (client) client->willSendRequest(job, redirectedRequest, d->m_response); - d->m_request.setURL(newURL); + d->m_firstRequest.setURL(newURL); return totalSize; } @@ -463,17 +463,17 @@ void ResourceHandleManager::setupPOST(ResourceHandle* job, struct curl_slist** h curl_easy_setopt(d->m_handle, CURLOPT_POST, TRUE); curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDSIZE, 0); - if (!job->request().httpBody()) + if (!job->firstRequest().httpBody()) return; - Vector<FormDataElement> elements = job->request().httpBody()->elements(); + Vector<FormDataElement> elements = job->firstRequest().httpBody()->elements(); size_t numElements = elements.size(); if (!numElements) return; // Do not stream for simple POST data if (numElements == 1) { - job->request().httpBody()->flatten(d->m_postBytes); + job->firstRequest().httpBody()->flatten(d->m_postBytes); if (d->m_postBytes.size() != 0) { curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDSIZE, d->m_postBytes.size()); curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDS, d->m_postBytes.data()); @@ -580,7 +580,7 @@ static void parseDataUrl(ResourceHandle* handle) if (!client) return; - String url = handle->request().url().string(); + String url = handle->firstRequest().url().string(); ASSERT(url.startsWith("data:", false)); int index = url.find(','); @@ -628,7 +628,7 @@ static void parseDataUrl(ResourceHandle* handle) void ResourceHandleManager::dispatchSynchronousJob(ResourceHandle* job) { - KURL kurl = job->request().url(); + KURL kurl = job->firstRequest().url(); if (kurl.protocolIs("data")) { parseDataUrl(job); @@ -659,7 +659,7 @@ void ResourceHandleManager::dispatchSynchronousJob(ResourceHandle* job) void ResourceHandleManager::startJob(ResourceHandle* job) { - KURL kurl = job->request().url(); + KURL kurl = job->firstRequest().url(); if (kurl.protocolIs("data")) { parseDataUrl(job); @@ -674,7 +674,7 @@ void ResourceHandleManager::startJob(ResourceHandle* job) // timeout will occur and do curl_multi_perform if (ret && ret != CURLM_CALL_MULTI_PERFORM) { #ifndef NDEBUG - fprintf(stderr, "Error %d starting job %s\n", ret, encodeWithURLEscapeSequences(job->request().url().string()).latin1().data()); + fprintf(stderr, "Error %d starting job %s\n", ret, encodeWithURLEscapeSequences(job->firstRequest().url().string()).latin1().data()); #endif job->cancel(); return; @@ -683,7 +683,7 @@ void ResourceHandleManager::startJob(ResourceHandle* job) void ResourceHandleManager::initializeHandle(ResourceHandle* job) { - KURL kurl = job->request().url(); + KURL kurl = job->firstRequest().url(); // Remove any fragment part, otherwise curl will send it as part of the request. kurl.removeFragmentIdentifier(); @@ -753,8 +753,8 @@ void ResourceHandleManager::initializeHandle(ResourceHandle* job) } struct curl_slist* headers = 0; - if (job->request().httpHeaderFields().size() > 0) { - HTTPHeaderMap customHeaders = job->request().httpHeaderFields(); + if (job->firstRequest().httpHeaderFields().size() > 0) { + HTTPHeaderMap customHeaders = job->firstRequest().httpHeaderFields(); HTTPHeaderMap::const_iterator end = customHeaders.end(); for (HTTPHeaderMap::const_iterator it = customHeaders.begin(); it != end; ++it) { String key = it->first; @@ -767,13 +767,13 @@ void ResourceHandleManager::initializeHandle(ResourceHandle* job) } } - if ("GET" == job->request().httpMethod()) + if ("GET" == job->firstRequest().httpMethod()) curl_easy_setopt(d->m_handle, CURLOPT_HTTPGET, TRUE); - else if ("POST" == job->request().httpMethod()) + else if ("POST" == job->firstRequest().httpMethod()) setupPOST(job, &headers); - else if ("PUT" == job->request().httpMethod()) + else if ("PUT" == job->firstRequest().httpMethod()) setupPUT(job, &headers); - else if ("HEAD" == job->request().httpMethod()) + else if ("HEAD" == job->firstRequest().httpMethod()) curl_easy_setopt(d->m_handle, CURLOPT_NOBODY, TRUE); if (headers) { diff --git a/WebCore/platform/network/mac/ResourceHandleMac.mm b/WebCore/platform/network/mac/ResourceHandleMac.mm index 9f64d4e..f7161ec 100644 --- a/WebCore/platform/network/mac/ResourceHandleMac.mm +++ b/WebCore/platform/network/mac/ResourceHandleMac.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2006-2009 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -56,8 +56,7 @@ typedef int NSInteger; using namespace WebCore; -@interface WebCoreResourceHandleAsDelegate : NSObject <NSURLConnectionDelegate> -{ +@interface WebCoreResourceHandleAsDelegate : NSObject <NSURLConnectionDelegate> { ResourceHandle* m_handle; } - (id)initWithHandle:(ResourceHandle*)handle; @@ -85,20 +84,48 @@ using namespace WebCore; #ifndef BUILDING_ON_TIGER -@interface WebCoreSynchronousLoader : NSObject <NSURLConnectionDelegate> { - NSURL *m_url; - NSString *m_user; - NSString *m_pass; - // Store the preemptively used initial credential so that if we get an authentication challenge, we won't use the same one again. - Credential m_initialCredential; - BOOL m_allowStoredCredentials; +class WebCoreSynchronousLoaderClient : public ResourceHandleClient { +public: + static PassOwnPtr<WebCoreSynchronousLoaderClient> create() + { + return adoptPtr(new WebCoreSynchronousLoaderClient); + } + + virtual ~WebCoreSynchronousLoaderClient(); + + void setAllowStoredCredentials(bool allow) { m_allowStoredCredentials = allow; } + NSURLResponse *response() { return m_response; } + NSMutableData *data() { return m_data; } + NSError *error() { return m_error; } + bool isDone() { return m_isDone; } + +private: + WebCoreSynchronousLoaderClient() + : m_allowStoredCredentials(false) + , m_response(0) + , m_data(0) + , m_error(0) + , m_isDone(false) + { + } + + virtual void willSendRequest(ResourceHandle*, ResourceRequest&, const ResourceResponse& /*redirectResponse*/); + virtual bool shouldUseCredentialStorage(ResourceHandle*); + virtual void didReceiveAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge&); + virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&); + virtual void didReceiveData(ResourceHandle*, const char*, int, int /*lengthReceived*/); + virtual void didFinishLoading(ResourceHandle*); + virtual void didFail(ResourceHandle*, const ResourceError&); +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + virtual bool canAuthenticateAgainstProtectionSpace(ResourceHandle*, const ProtectionSpace&); +#endif + + bool m_allowStoredCredentials; NSURLResponse *m_response; NSMutableData *m_data; NSError *m_error; - BOOL m_isDone; -} -+ (NSData *)loadRequest:(NSURLRequest *)request allowStoredCredentials:(BOOL)allowStoredCredentials returningResponse:(NSURLResponse **)response error:(NSError **)error; -@end + bool m_isDone; +}; static NSString *WebCoreSynchronousLoaderRunLoopMode = @"WebCoreSynchronousLoaderRunLoopMode"; @@ -161,12 +188,51 @@ bool ResourceHandle::didSendBodyDataDelegateExists() return NSFoundationVersionNumber > MaxFoundationVersionWithoutdidSendBodyDataDelegate; } -static NSURLConnection *createNSURLConnection(NSURLRequest *request, id delegate, bool shouldUseCredentialStorage) +void ResourceHandle::createNSURLConnection(id delegate, bool shouldUseCredentialStorage, bool shouldContentSniff) { -#if defined(BUILDING_ON_TIGER) - UNUSED_PARAM(shouldUseCredentialStorage); - return [[NSURLConnection alloc] initWithRequest:request delegate:delegate]; -#else + // Credentials for ftp can only be passed in URL, the connection:didReceiveAuthenticationChallenge: delegate call won't be made. + if ((!d->m_user.isEmpty() || !d->m_pass.isEmpty()) +#ifndef BUILDING_ON_TIGER + && !firstRequest().url().protocolInHTTPFamily() // On Tiger, always pass credentials in URL, so that they get stored even if the request gets cancelled right away. +#endif + ) { + KURL urlWithCredentials(firstRequest().url()); + urlWithCredentials.setUser(d->m_user); + urlWithCredentials.setPass(d->m_pass); + firstRequest().setURL(urlWithCredentials); + } + + // If a URL already has cookies, then we'll relax the 3rd party cookie policy and accept new cookies. + NSHTTPCookieStorage *sharedStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; + if ([sharedStorage cookieAcceptPolicy] == NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain && [[sharedStorage cookiesForURL:firstRequest().url()] count]) + firstRequest().setFirstPartyForCookies(firstRequest().url()); + +#if !defined(BUILDING_ON_TIGER) + if (shouldUseCredentialStorage && firstRequest().url().protocolInHTTPFamily()) { + if (d->m_user.isEmpty() && d->m_pass.isEmpty()) { + // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication, + // try and reuse the credential preemptively, as allowed by RFC 2617. + d->m_initialCredential = CredentialStorage::get(firstRequest().url()); + } else { + // If there is already a protection space known for the URL, update stored credentials before sending a request. + // This makes it possible to implement logout by sending an XMLHttpRequest with known incorrect credentials, and aborting it immediately + // (so that an authentication dialog doesn't pop up). + CredentialStorage::set(Credential(d->m_user, d->m_pass, CredentialPersistenceNone), firstRequest().url()); + } + } + + if (!d->m_initialCredential.isEmpty()) { + // FIXME: Support Digest authentication, and Proxy-Authorization. + String authHeader = "Basic " + encodeBasicAuthorization(d->m_initialCredential.user(), d->m_initialCredential.password()); + firstRequest().addHTTPHeaderField("Authorization", authHeader); + } + + NSURLRequest *nsRequest = firstRequest().nsURLRequest(); + if (!shouldContentSniff) { + NSMutableURLRequest *mutableRequest = [[nsRequest copy] autorelease]; + wkSetNSURLRequestShouldContentSniff(mutableRequest, NO); + nsRequest = mutableRequest; + } #if !defined(BUILDING_ON_LEOPARD) ASSERT([NSURLConnection instancesRespondToSelector:@selector(_initWithRequest:delegate:usesCache:maxContentLength:startImmediately:connectionProperties:)]); @@ -178,10 +244,18 @@ static NSURLConnection *createNSURLConnection(NSURLRequest *request, id delegate if (supportsSettingConnectionProperties) { NSDictionary *sessionID = shouldUseCredentialStorage ? [NSDictionary dictionary] : [NSDictionary dictionaryWithObject:@"WebKitPrivateSession" forKey:@"_kCFURLConnectionSessionID"]; NSDictionary *propertyDictionary = [NSDictionary dictionaryWithObject:sessionID forKey:@"kCFURLConnectionSocketStreamProperties"]; - return [[NSURLConnection alloc] _initWithRequest:request delegate:delegate usesCache:YES maxContentLength:0 startImmediately:NO connectionProperties:propertyDictionary]; + d->m_connection.adoptNS([[NSURLConnection alloc] _initWithRequest:nsRequest delegate:delegate usesCache:YES maxContentLength:0 startImmediately:NO connectionProperties:propertyDictionary]); + return; } - return [[NSURLConnection alloc] initWithRequest:request delegate:delegate startImmediately:NO]; + d->m_connection.adoptNS([[NSURLConnection alloc] initWithRequest:nsRequest delegate:delegate startImmediately:NO]); + return; + +#else + // Building on Tiger. Don't use WebCore credential storage, don't try to disable content sniffing. + UNUSED_PARAM(shouldUseCredentialStorage); + UNUSED_PARAM(shouldContentSniff); + d->m_connection.adoptNS([[NSURLConnection alloc] initWithRequest:firstRequest().nsURLRequest() delegate:delegate]); #endif } @@ -206,69 +280,24 @@ bool ResourceHandle::start(Frame* frame) d->m_proxy.adoptNS(wkCreateNSURLConnectionDelegateProxy()); [static_cast<WebCoreNSURLConnectionDelegateProxy*>(d->m_proxy.get()) setDelegate:ResourceHandle::delegate()]; - if ((!d->m_user.isEmpty() || !d->m_pass.isEmpty()) -#ifndef BUILDING_ON_TIGER - && !d->m_request.url().protocolInHTTPFamily() // On Tiger, always pass credentials in URL, so that they get stored even if the request gets cancelled right away. -#endif - ) { - // Credentials for ftp can only be passed in URL, the connection:didReceiveAuthenticationChallenge: delegate call won't be made. - KURL urlWithCredentials(d->m_request.url()); - urlWithCredentials.setUser(d->m_user); - urlWithCredentials.setPass(d->m_pass); - d->m_request.setURL(urlWithCredentials); - } - bool shouldUseCredentialStorage = !client() || client()->shouldUseCredentialStorage(this); -#ifndef BUILDING_ON_TIGER - if (shouldUseCredentialStorage && d->m_request.url().protocolInHTTPFamily()) { - if (d->m_user.isEmpty() && d->m_pass.isEmpty()) { - // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication, - // try and reuse the credential preemptively, as allowed by RFC 2617. - d->m_initialCredential = CredentialStorage::get(d->m_request.url()); - } else { - // If there is already a protection space known for the URL, update stored credentials before sending a request. - // This makes it possible to implement logout by sending an XMLHttpRequest with known incorrect credentials, and aborting it immediately - // (so that an authentication dialog doesn't pop up). - CredentialStorage::set(Credential(d->m_user, d->m_pass, CredentialPersistenceNone), d->m_request.url()); - } - } - - if (!d->m_initialCredential.isEmpty()) { - // FIXME: Support Digest authentication, and Proxy-Authorization. - String authHeader = "Basic " + encodeBasicAuthorization(d->m_initialCredential.user(), d->m_initialCredential.password()); - d->m_request.addHTTPHeaderField("Authorization", authHeader); - } -#endif - if (!ResourceHandle::didSendBodyDataDelegateExists()) - associateStreamWithResourceHandle([d->m_request.nsURLRequest() HTTPBodyStream], this); + associateStreamWithResourceHandle([firstRequest().nsURLRequest() HTTPBodyStream], this); #ifdef BUILDING_ON_TIGER // A conditional request sent by WebCore (e.g. to update appcache) can be for a resource that is not cacheable by NSURLConnection, // which can get confused and fail to load it in this case. - if (d->m_request.isConditional()) - d->m_request.setCachePolicy(ReloadIgnoringCacheData); + if (firstRequest().isConditional()) + firstRequest().setCachePolicy(ReloadIgnoringCacheData); #endif d->m_needsSiteSpecificQuirks = frame->settings() && frame->settings()->needsSiteSpecificQuirks(); - // If a URL already has cookies, then we'll relax the 3rd party cookie policy and accept new cookies. - NSHTTPCookieStorage *sharedStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; - if ([sharedStorage cookieAcceptPolicy] == NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain - && [[sharedStorage cookiesForURL:d->m_request.url()] count]) - d->m_request.setFirstPartyForCookies(d->m_request.url()); - - NSURLConnection *connection; - - if (d->m_shouldContentSniff || frame->settings()->localFileContentSniffingEnabled()) - connection = createNSURLConnection(d->m_request.nsURLRequest(), d->m_proxy.get(), shouldUseCredentialStorage); - else { - NSMutableURLRequest *request = [d->m_request.nsURLRequest() mutableCopy]; - wkSetNSURLRequestShouldContentSniff(request, NO); - connection = createNSURLConnection(request, d->m_proxy.get(), shouldUseCredentialStorage); - [request release]; - } + createNSURLConnection( + d->m_proxy.get(), + shouldUseCredentialStorage, + d->m_shouldContentSniff || frame->settings()->localFileContentSniffingEnabled()); #ifndef BUILDING_ON_TIGER bool scheduled = false; @@ -276,7 +305,7 @@ bool ResourceHandle::start(Frame* frame) SchedulePairHashSet::iterator end = scheduledPairs->end(); for (SchedulePairHashSet::iterator it = scheduledPairs->begin(); it != end; ++it) { if (NSRunLoop *runLoop = (*it)->nsRunLoop()) { - [connection scheduleInRunLoop:runLoop forMode:(NSString *)(*it)->mode()]; + [connection() scheduleInRunLoop:runLoop forMode:(NSString *)(*it)->mode()]; scheduled = true; } } @@ -285,7 +314,7 @@ bool ResourceHandle::start(Frame* frame) // Start the connection if we did schedule with at least one runloop. // We can't start the connection until we have one runloop scheduled. if (scheduled) - [connection start]; + [connection() start]; else d->m_startWhenScheduled = true; #endif @@ -294,15 +323,11 @@ bool ResourceHandle::start(Frame* frame) isInitializingConnection = NO; #endif - LOG(Network, "Handle %p starting connection %p for %@", this, connection, d->m_request.nsURLRequest()); + LOG(Network, "Handle %p starting connection %p for %@", this, connection(), firstRequest().nsURLRequest()); - d->m_connection = connection; - if (d->m_connection) { - [connection release]; - if (d->m_defersLoading) - wkSetNSURLConnectionDefersCallbacks(d->m_connection.get(), YES); + wkSetNSURLConnectionDefersCallbacks(connection(), YES); return true; } @@ -321,7 +346,7 @@ void ResourceHandle::cancel() [[d->m_currentMacChallenge sender] cancelAuthenticationChallenge:d->m_currentMacChallenge]; if (!ResourceHandle::didSendBodyDataDelegateExists()) - disassociateStreamWithResourceHandle([d->m_request.nsURLRequest() HTTPBodyStream]); + disassociateStreamWithResourceHandle([firstRequest().nsURLRequest() HTTPBodyStream]); [d->m_connection.get() cancel]; } @@ -435,43 +460,63 @@ bool ResourceHandle::willLoadFromCache(ResourceRequest& request, Frame*) #endif } -void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials storedCredentials, ResourceError& error, ResourceResponse& response, Vector<char>& data, Frame*) +void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials storedCredentials, ResourceError& error, ResourceResponse& response, Vector<char>& data, Frame* frame) { + LOG(Network, "ResourceHandle::loadResourceSynchronously:%@ allowStoredCredentials:%u", request.nsURLRequest(), storedCredentials); + NSError *nsError = nil; - NSURLResponse *nsURLResponse = nil; NSData *result = nil; ASSERT(!request.isEmpty()); - NSMutableURLRequest *mutableRequest = nil; - if (!shouldContentSniffURL(request.url())) { - mutableRequest = [[request.nsURLRequest() mutableCopy] autorelease]; - wkSetNSURLRequestShouldContentSniff(mutableRequest, NO); - } +#ifndef BUILDING_ON_TIGER + OwnPtr<WebCoreSynchronousLoaderClient> client = WebCoreSynchronousLoaderClient::create(); + client->setAllowStoredCredentials(storedCredentials == AllowStoredCredentials); - // If a URL already has cookies, then we'll ignore the 3rd party cookie policy and accept new cookies. - NSHTTPCookieStorage *sharedStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; - if ([sharedStorage cookieAcceptPolicy] == NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain - && [[sharedStorage cookiesForURL:request.url()] count]) { - if (!mutableRequest) - mutableRequest = [[request.nsURLRequest() mutableCopy] autorelease]; - [mutableRequest setMainDocumentURL:[mutableRequest URL]]; + RefPtr<ResourceHandle> handle = adoptRef(new ResourceHandle(request, client.get(), false /*defersLoading*/, true /*shouldContentSniff*/)); + + if (handle->d->m_scheduledFailureType != NoFailure) { + error = frame->loader()->blockedError(request); + return; } + + handle->createNSURLConnection( + handle->delegate(), // A synchronous request cannot turn into a download, so there is no need to proxy the delegate. + storedCredentials == AllowStoredCredentials, + handle->shouldContentSniff() || frame->settings()->localFileContentSniffingEnabled()); + + [handle->connection() scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:WebCoreSynchronousLoaderRunLoopMode]; + [handle->connection() start]; - NSURLRequest *nsRequest = mutableRequest ? mutableRequest : request.nsURLRequest(); - - BEGIN_BLOCK_OBJC_EXCEPTIONS; + while (!client->isDone()) + [[NSRunLoop currentRunLoop] runMode:WebCoreSynchronousLoaderRunLoopMode beforeDate:[NSDate distantFuture]]; + + result = client->data(); + nsURLResponse = client->response(); + nsError = client->error(); -#ifndef BUILDING_ON_TIGER - result = [WebCoreSynchronousLoader loadRequest:nsRequest allowStoredCredentials:(storedCredentials == AllowStoredCredentials) returningResponse:&nsURLResponse error:&nsError]; + [handle->connection() cancel]; + #else UNUSED_PARAM(storedCredentials); - result = [NSURLConnection sendSynchronousRequest:nsRequest returningResponse:&nsURLResponse error:&nsError]; -#endif + UNUSED_PARAM(frame); + NSURLRequest *firstRequest = request.nsURLRequest(); + + // If a URL already has cookies, then we'll relax the 3rd party cookie policy and accept new cookies. + NSHTTPCookieStorage *sharedStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; + if ([sharedStorage cookieAcceptPolicy] == NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain && [[sharedStorage cookiesForURL:[firstRequest URL]] count]) { + NSMutableURLRequest *mutableRequest = [[firstRequest mutableCopy] autorelease]; + [mutableRequest setMainDocumentURL:[mutableRequest URL]]; + firstRequest = mutableRequest; + } + + BEGIN_BLOCK_OBJC_EXCEPTIONS; + result = [NSURLConnection sendSynchronousRequest:firstRequest returningResponse:&nsURLResponse error:&nsError]; END_BLOCK_OBJC_EXCEPTIONS; +#endif - if (nsError == nil) + if (!nsError) response = nsURLResponse; else { response = ResourceResponse(request.url(), String(), 0, String(), String()); @@ -536,16 +581,25 @@ void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChall } #ifndef BUILDING_ON_TIGER - if (!challenge.previousFailureCount() && (!client() || client()->shouldUseCredentialStorage(this))) { - Credential credential = CredentialStorage::get(challenge.protectionSpace()); - if (!credential.isEmpty() && credential != d->m_initialCredential) { - ASSERT(credential.persistence() == CredentialPersistenceNone); - if (challenge.failureResponse().httpStatusCode() == 401) { - // Store the credential back, possibly adding it as a default for this directory. - CredentialStorage::set(credential, challenge.protectionSpace(), d->m_request.url()); + if (!client() || client()->shouldUseCredentialStorage(this)) { + if (!d->m_initialCredential.isEmpty() || challenge.previousFailureCount()) { + // The stored credential wasn't accepted, stop using it. + // There is a race condition here, since a different credential might have already been stored by another ResourceHandle, + // but the observable effect should be very minor, if any. + CredentialStorage::remove(challenge.protectionSpace()); + } + + if (!challenge.previousFailureCount()) { + Credential credential = CredentialStorage::get(challenge.protectionSpace()); + if (!credential.isEmpty() && credential != d->m_initialCredential) { + ASSERT(credential.persistence() == CredentialPersistenceNone); + if (challenge.failureResponse().httpStatusCode() == 401) { + // Store the credential back, possibly adding it as a default for this directory. + CredentialStorage::set(credential, challenge.protectionSpace(), firstRequest().url()); + } + [challenge.sender() useCredential:mac(credential) forAuthenticationChallenge:mac(challenge)]; + return; } - [challenge.sender() useCredential:mac(credential) forAuthenticationChallenge:mac(challenge)]; - return; } } #endif @@ -604,7 +658,7 @@ void ResourceHandle::receivedCredential(const AuthenticationChallenge& challenge Credential webCredential(credential, CredentialPersistenceNone); KURL urlToStore; if (challenge.failureResponse().httpStatusCode() == 401) - urlToStore = d->m_request.url(); + urlToStore = firstRequest().url(); CredentialStorage::set(webCredential, core([d->m_currentMacChallenge protectionSpace]), urlToStore); [[d->m_currentMacChallenge sender] useCredential:mac(webCredential) forAuthenticationChallenge:d->m_currentMacChallenge]; } else @@ -679,11 +733,11 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen NSMutableURLRequest *mutableRequest = [newRequest mutableCopy]; [mutableRequest setHTTPMethod:lastHTTPMethod]; - FormData* body = m_handle->request().httpBody(); + FormData* body = m_handle->firstRequest().httpBody(); if (!equalIgnoringCase(lastHTTPMethod, "GET") && body && !body->isEmpty()) WebCore::setHTTPBody(mutableRequest, body); - String originalContentType = m_handle->request().httpContentType(); + String originalContentType = m_handle->firstRequest().httpContentType(); if (!originalContentType.isEmpty()) [mutableRequest setValue:originalContentType forHTTPHeaderField:@"Content-Type"]; @@ -779,7 +833,7 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen if (statusCode != 304) [r adjustMIMETypeIfNecessary]; - if ([m_handle->request().nsURLRequest() _propertyForKey:@"ForceHTMLMIMEType"]) + if ([m_handle->firstRequest().nsURLRequest() _propertyForKey:@"ForceHTMLMIMEType"]) [r _setMIMEType:@"text/html"]; #if ENABLE(WML) @@ -855,7 +909,7 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen CallbackGuard guard; if (!ResourceHandle::didSendBodyDataDelegateExists()) - disassociateStreamWithResourceHandle([m_handle->request().nsURLRequest() HTTPBodyStream]); + disassociateStreamWithResourceHandle([m_handle->firstRequest().nsURLRequest() HTTPBodyStream]); m_handle->client()->didFinishLoading(m_handle); } @@ -871,7 +925,7 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen CallbackGuard guard; if (!ResourceHandle::didSendBodyDataDelegateExists()) - disassociateStreamWithResourceHandle([m_handle->request().nsURLRequest() HTTPBodyStream]); + disassociateStreamWithResourceHandle([m_handle->firstRequest().nsURLRequest() HTTPBodyStream]); m_handle->client()->didFail(m_handle, error); } @@ -947,220 +1001,69 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen #ifndef BUILDING_ON_TIGER -@implementation WebCoreSynchronousLoader - -- (BOOL)_isDone -{ - return m_isDone; -} - -- (void)dealloc +WebCoreSynchronousLoaderClient::~WebCoreSynchronousLoaderClient() { - [m_url release]; - [m_user release]; - [m_pass release]; [m_response release]; [m_data release]; [m_error release]; - - [super dealloc]; } -- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)redirectResponse +void WebCoreSynchronousLoaderClient::willSendRequest(ResourceHandle* handle, ResourceRequest& request, const ResourceResponse& /*redirectResponse*/) { - UNUSED_PARAM(connection); - - LOG(Network, "WebCoreSynchronousLoader delegate connection:%p willSendRequest:%@ redirectResponse:%p", connection, [newRequest description], redirectResponse); - // FIXME: This needs to be fixed to follow the redirect correctly even for cross-domain requests. - if (m_url && !protocolHostAndPortAreEqual(m_url, [newRequest URL])) { + if (!protocolHostAndPortAreEqual(handle->firstRequest().url(), request.url())) { + ASSERT(!m_error); m_error = [[NSError alloc] initWithDomain:NSURLErrorDomain code:NSURLErrorBadServerResponse userInfo:nil]; - m_isDone = YES; - return nil; - } - - NSURL *copy = [[newRequest URL] copy]; - [m_url release]; - m_url = copy; - - if (redirectResponse) { - // Take user/pass out of the URL. - [m_user release]; - [m_pass release]; - m_user = [[m_url user] copy]; - m_pass = [[m_url password] copy]; - if (m_user || m_pass) { - ResourceRequest requestWithoutCredentials = newRequest; - requestWithoutCredentials.removeCredentials(); - return requestWithoutCredentials.nsURLRequest(); - } + m_isDone = true; + request = 0; + return; } - - return newRequest; } -- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection +bool WebCoreSynchronousLoaderClient::shouldUseCredentialStorage(ResourceHandle*) { - UNUSED_PARAM(connection); - - LOG(Network, "WebCoreSynchronousLoader delegate connectionShouldUseCredentialStorage:%p", connection); - // FIXME: We should ask FrameLoaderClient whether using credential storage is globally forbidden. return m_allowStoredCredentials; } -- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) +bool WebCoreSynchronousLoaderClient::canAuthenticateAgainstProtectionSpace(ResourceHandle*, const ProtectionSpace&) { - UNUSED_PARAM(connection); - - LOG(Network, "WebCoreSynchronousLoader delegate connection:%p didReceiveAuthenticationChallenge:%p", connection, challenge); + // FIXME: We should ask FrameLoaderClient. + return true; +} +#endif - if (m_user && m_pass) { - NSURLCredential *credential = [[NSURLCredential alloc] initWithUser:m_user - password:m_pass - persistence:NSURLCredentialPersistenceNone]; - KURL urlToStore; - if ([[challenge failureResponse] isKindOfClass:[NSHTTPURLResponse class]] && [(NSHTTPURLResponse*)[challenge failureResponse] statusCode] == 401) - urlToStore = m_url; - CredentialStorage::set(core(credential), core([challenge protectionSpace]), urlToStore); - - [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; - [credential release]; - [m_user release]; - [m_pass release]; - m_user = 0; - m_pass = 0; - return; - } - if ([challenge previousFailureCount] == 0 && m_allowStoredCredentials) { - Credential credential = CredentialStorage::get(core([challenge protectionSpace])); - if (!credential.isEmpty() && credential != m_initialCredential) { - ASSERT(credential.persistence() == CredentialPersistenceNone); - if ([[challenge failureResponse] isKindOfClass:[NSHTTPURLResponse class]] && [(NSHTTPURLResponse *)[challenge failureResponse] statusCode] == 401) { - // Store the credential back, possibly adding it as a default for this directory. - CredentialStorage::set(credential, core([challenge protectionSpace]), m_url); - } - [[challenge sender] useCredential:mac(credential) forAuthenticationChallenge:challenge]; - return; - } - } +void WebCoreSynchronousLoaderClient::didReceiveAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge& challenge) +{ // FIXME: The user should be asked for credentials, as in async case. - [[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge]; + [challenge.sender() continueWithoutCredentialForAuthenticationChallenge:challenge.nsURLAuthenticationChallenge()]; } -- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response +void WebCoreSynchronousLoaderClient::didReceiveResponse(ResourceHandle*, const ResourceResponse& response) { - UNUSED_PARAM(connection); - - LOG(Network, "WebCoreSynchronousLoader delegate connection:%p didReceiveResponse:%p (HTTP status %d, reported MIMEType '%s')", connection, response, [response respondsToSelector:@selector(statusCode)] ? [(id)response statusCode] : 0, [[response MIMEType] UTF8String]); - - NSURLResponse *r = [response copy]; - [m_response release]; - m_response = r; + m_response = [response.nsURLResponse() copy]; } -- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data +void WebCoreSynchronousLoaderClient::didReceiveData(ResourceHandle*, const char* data, int length, int /*lengthReceived*/) { - UNUSED_PARAM(connection); - - LOG(Network, "WebCoreSynchronousLoader delegate connection:%p didReceiveData:%p", connection, data); - if (!m_data) m_data = [[NSMutableData alloc] init]; - - [m_data appendData:data]; + [m_data appendBytes:data length:length]; } -- (void)connectionDidFinishLoading:(NSURLConnection *)connection +void WebCoreSynchronousLoaderClient::didFinishLoading(ResourceHandle*) { - UNUSED_PARAM(connection); - - LOG(Network, "WebCoreSynchronousLoader delegate connectionDidFinishLoading:%p", connection); - - m_isDone = YES; + m_isDone = true; } -- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error +void WebCoreSynchronousLoaderClient::didFail(ResourceHandle*, const ResourceError& error) { - UNUSED_PARAM(connection); - - LOG(Network, "WebCoreSynchronousLoader delegate connection:%p didFailWithError:%@", connection, error); - ASSERT(!m_error); - - m_error = [error retain]; - m_isDone = YES; -} - -- (NSData *)_data -{ - return [[m_data retain] autorelease]; -} - -- (NSURLResponse *)_response -{ - return [[m_response retain] autorelease]; -} -- (NSError *)_error -{ - return [[m_error retain] autorelease]; + m_error = [error copy]; + m_isDone = true; } -+ (NSData *)loadRequest:(NSURLRequest *)request allowStoredCredentials:(BOOL)allowStoredCredentials returningResponse:(NSURLResponse **)response error:(NSError **)error -{ - LOG(Network, "WebCoreSynchronousLoader loadRequest:%@ allowStoredCredentials:%u", request, allowStoredCredentials); - - WebCoreSynchronousLoader *delegate = [[WebCoreSynchronousLoader alloc] init]; - - KURL url([request URL]); - delegate->m_user = [nsStringNilIfEmpty(url.user()) retain]; - delegate->m_pass = [nsStringNilIfEmpty(url.pass()) retain]; - delegate->m_allowStoredCredentials = allowStoredCredentials; - - NSURLConnection *connection; - - // Take user/pass out of the URL. - // Credentials for ftp can only be passed in URL, the connection:didReceiveAuthenticationChallenge: delegate call won't be made. - if ((delegate->m_user || delegate->m_pass) && url.protocolInHTTPFamily()) { - ResourceRequest requestWithoutCredentials = request; - requestWithoutCredentials.removeCredentials(); - connection = createNSURLConnection(requestWithoutCredentials.nsURLRequest(), delegate, allowStoredCredentials); - } else { - // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication, - // try and reuse the credential preemptively, as allowed by RFC 2617. - ResourceRequest requestWithInitialCredentials = request; - if (allowStoredCredentials && url.protocolInHTTPFamily()) - delegate->m_initialCredential = CredentialStorage::get(url); - - if (!delegate->m_initialCredential.isEmpty()) { - String authHeader = "Basic " + encodeBasicAuthorization(delegate->m_initialCredential.user(), delegate->m_initialCredential.password()); - requestWithInitialCredentials.addHTTPHeaderField("Authorization", authHeader); - } - connection = createNSURLConnection(requestWithInitialCredentials.nsURLRequest(), delegate, allowStoredCredentials); - } - - [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:WebCoreSynchronousLoaderRunLoopMode]; - [connection start]; - - while (![delegate _isDone]) - [[NSRunLoop currentRunLoop] runMode:WebCoreSynchronousLoaderRunLoopMode beforeDate:[NSDate distantFuture]]; - - NSData *data = [delegate _data]; - *response = [delegate _response]; - *error = [delegate _error]; - - [connection cancel]; - - [connection release]; - [delegate release]; - - LOG(Network, "WebCoreSynchronousLoader done"); - - return data; -} - -@end - #endif diff --git a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp index 1ae24ff..131f924 100644 --- a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp +++ b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp @@ -150,7 +150,7 @@ QNetworkReplyHandler::QNetworkReplyHandler(ResourceHandle* handle, LoadMode load , m_shouldForwardData(false) , m_redirectionTries(gMaxRecursionLimit) { - const ResourceRequest &r = m_resourceHandle->request(); + const ResourceRequest &r = m_resourceHandle->firstRequest(); if (r.httpMethod() == "GET") m_method = QNetworkAccessManager::GetOperation; @@ -309,7 +309,7 @@ void QNetworkReplyHandler::sendResponseIfNeeded() } KURL url(m_reply->url()); - ResourceResponse response(url, mimeType, + ResourceResponse response(url, mimeType.lower(), m_reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), encoding, String()); @@ -358,7 +358,7 @@ void QNetworkReplyHandler::sendResponseIfNeeded() } m_redirected = true; - ResourceRequest newRequest = m_resourceHandle->request(); + ResourceRequest newRequest = m_resourceHandle->firstRequest(); newRequest.setURL(newUrl); if (((statusCode >= 301 && statusCode <= 303) || statusCode == 307) && newRequest.httpMethod() == "POST") { @@ -442,7 +442,7 @@ void QNetworkReplyHandler::start() m_reply = manager->get(m_request); break; case QNetworkAccessManager::PostOperation: { - FormDataIODevice* postDevice = new FormDataIODevice(d->m_request.httpBody()); + FormDataIODevice* postDevice = new FormDataIODevice(d->m_firstRequest.httpBody()); m_reply = manager->post(m_request, postDevice); postDevice->setParent(m_reply); break; @@ -451,7 +451,7 @@ void QNetworkReplyHandler::start() m_reply = manager->head(m_request); break; case QNetworkAccessManager::PutOperation: { - FormDataIODevice* putDevice = new FormDataIODevice(d->m_request.httpBody()); + FormDataIODevice* putDevice = new FormDataIODevice(d->m_firstRequest.httpBody()); m_reply = manager->put(m_request, putDevice); putDevice->setParent(m_reply); break; @@ -464,7 +464,7 @@ void QNetworkReplyHandler::start() #endif #if QT_VERSION >= 0x040700 case QNetworkAccessManager::CustomOperation: - m_reply = manager->sendCustomRequest(m_request, m_resourceHandle->request().httpMethod().latin1().data()); + m_reply = manager->sendCustomRequest(m_request, m_resourceHandle->firstRequest().httpMethod().latin1().data()); break; #endif case QNetworkAccessManager::UnknownOperation: { @@ -494,7 +494,7 @@ void QNetworkReplyHandler::start() connect(m_reply, SIGNAL(readyRead()), this, SLOT(forwardData()), SIGNAL_CONN); - if (m_resourceHandle->request().reportUploadProgress()) { + if (m_resourceHandle->firstRequest().reportUploadProgress()) { connect(m_reply, SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(uploadProgress(qint64, qint64)), SIGNAL_CONN); } diff --git a/WebCore/platform/network/qt/ResourceHandleQt.cpp b/WebCore/platform/network/qt/ResourceHandleQt.cpp index ff75a94..f91eecb 100644 --- a/WebCore/platform/network/qt/ResourceHandleQt.cpp +++ b/WebCore/platform/network/qt/ResourceHandleQt.cpp @@ -43,7 +43,6 @@ // FIXME: WebCore including these headers from WebKit is a massive layering violation. #include "qwebframe_p.h" -#include "qwebpage_p.h" #include <QAbstractNetworkCache> #include <QCoreApplication> @@ -130,10 +129,10 @@ bool ResourceHandle::start(Frame* frame) if (!(d->m_user.isEmpty() || d->m_pass.isEmpty())) { // If credentials were specified for this request, add them to the url, // so that they will be passed to QNetworkRequest. - KURL urlWithCredentials(d->m_request.url()); + KURL urlWithCredentials(firstRequest().url()); urlWithCredentials.setUser(d->m_user); urlWithCredentials.setPass(d->m_pass); - d->m_request.setURL(urlWithCredentials); + d->m_firstRequest.setURL(urlWithCredentials); } getInternal()->m_frame = static_cast<FrameLoaderClientQt*>(frame->loader()->client())->webFrame(); @@ -195,10 +194,10 @@ void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, S if (!(d->m_user.isEmpty() || d->m_pass.isEmpty())) { // If credentials were specified for this request, add them to the url, // so that they will be passed to QNetworkRequest. - KURL urlWithCredentials(d->m_request.url()); + KURL urlWithCredentials(d->m_firstRequest.url()); urlWithCredentials.setUser(d->m_user); urlWithCredentials.setPass(d->m_pass); - d->m_request.setURL(urlWithCredentials); + d->m_firstRequest.setURL(urlWithCredentials); } d->m_frame = static_cast<FrameLoaderClientQt*>(frame->loader()->client())->webFrame(); d->m_job = new QNetworkReplyHandler(handle.get(), QNetworkReplyHandler::LoadNormal); diff --git a/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/WebCore/platform/network/soup/ResourceHandleSoup.cpp index e4f2a4b..96a2f25 100644 --- a/WebCore/platform/network/soup/ResourceHandleSoup.cpp +++ b/WebCore/platform/network/soup/ResourceHandleSoup.cpp @@ -188,9 +188,9 @@ static void restartedCallback(SoupMessage* msg, gpointer data) char* uri = soup_uri_to_string(soup_message_get_uri(msg), false); String location = String(uri); g_free(uri); - KURL newURL = KURL(handle->request().url(), location); + KURL newURL = KURL(handle->firstRequest().url(), location); - ResourceRequest request = handle->request(); + ResourceRequest request = handle->firstRequest(); ResourceResponse response; request.setURL(newURL); request.setHTTPMethod(msg->method); @@ -354,7 +354,7 @@ static gboolean parseDataUrl(gpointer callbackData) if (!client) return false; - String url = handle->request().url().string(); + String url = handle->firstRequest().url().string(); ASSERT(url.startsWith("data:", false)); int index = url.find(','); @@ -377,7 +377,7 @@ static gboolean parseDataUrl(gpointer callbackData) String charset = extractCharsetFromMediaType(mediaType); ResourceResponse response; - response.setURL(handle->request().url()); + response.setURL(handle->firstRequest().url()); response.setMimeType(mimeType); if (isBase64) { @@ -478,7 +478,7 @@ static bool startHttp(ResourceHandle* handle) ResourceHandleInternal* d = handle->getInternal(); - ResourceRequest request(handle->request()); + ResourceRequest request(handle->firstRequest()); KURL url(request.url()); url.removeFragmentIdentifier(); request.setURL(url); @@ -504,7 +504,7 @@ static bool startHttp(ResourceHandle* handle) #endif g_object_set_data(G_OBJECT(d->m_msg), "resourceHandle", reinterpret_cast<void*>(handle)); - FormData* httpBody = d->m_request.httpBody(); + FormData* httpBody = d->m_firstRequest.httpBody(); if (httpBody && !httpBody->isEmpty()) { size_t numElements = httpBody->elements().size(); @@ -512,7 +512,7 @@ static bool startHttp(ResourceHandle* handle) if (numElements < 2) { Vector<char> body; httpBody->flatten(body); - soup_message_set_request(d->m_msg, d->m_request.httpContentType().utf8().data(), + soup_message_set_request(d->m_msg, d->m_firstRequest.httpContentType().utf8().data(), SOUP_MEMORY_COPY, body.data(), body.size()); } else { /* @@ -590,7 +590,7 @@ bool ResourceHandle::start(Frame* frame) if (frame && !frame->page()) return false; - KURL url = request().url(); + KURL url = firstRequest().url(); String urlString = url.string(); String protocol = url.protocol(); @@ -889,7 +889,7 @@ static bool startGio(ResourceHandle* handle, KURL url) ResourceHandleInternal* d = handle->getInternal(); - if (handle->request().httpMethod() != "GET" && handle->request().httpMethod() != "POST") + if (handle->firstRequest().httpMethod() != "GET" && handle->firstRequest().httpMethod() != "POST") return false; // GIO doesn't know how to handle refs and queries, so remove them diff --git a/WebCore/platform/qt/CursorQt.cpp b/WebCore/platform/qt/CursorQt.cpp index 2e495e7..6017daa 100644 --- a/WebCore/platform/qt/CursorQt.cpp +++ b/WebCore/platform/qt/CursorQt.cpp @@ -44,12 +44,12 @@ namespace WebCore { Cursor::Cursor(PlatformCursor p) - : m_impl(p) + : m_platformCursor(p) { } Cursor::Cursor(const Cursor& other) - : m_impl(other.m_impl) + : m_platformCursor(other.m_platformCursor) { } @@ -61,13 +61,13 @@ Cursor::Cursor(Image* image, const IntPoint& hotSpot) { #ifndef QT_NO_CURSOR IntPoint effectiveHotSpot = determineHotSpot(image, hotSpot); - m_impl = QCursor(*(image->nativeImageForCurrentFrame()), effectiveHotSpot.x(), effectiveHotSpot.y()); + m_platformCursor = QCursor(*(image->nativeImageForCurrentFrame()), effectiveHotSpot.x(), effectiveHotSpot.y()); #endif } Cursor& Cursor::operator=(const Cursor& other) { - m_impl = other.m_impl; + m_platformCursor = other.m_platformCursor; return *this; } diff --git a/WebCore/platform/qt/GeolocationServiceQt.cpp b/WebCore/platform/qt/GeolocationServiceQt.cpp index e24d497..3562eb9 100644 --- a/WebCore/platform/qt/GeolocationServiceQt.cpp +++ b/WebCore/platform/qt/GeolocationServiceQt.cpp @@ -55,6 +55,7 @@ GeolocationServiceQt::GeolocationServiceQt(GeolocationServiceClient* client) GeolocationServiceQt::~GeolocationServiceQt() { + delete m_location; } void GeolocationServiceQt::positionUpdated(const QGeoPositionInfo &geoPosition) @@ -65,20 +66,19 @@ void GeolocationServiceQt::positionUpdated(const QGeoPositionInfo &geoPosition) QGeoCoordinate coord = geoPosition.coordinate(); double latitude = coord.latitude(); double longitude = coord.longitude(); - bool providesAltitude = true; + bool providesAltitude = (geoPosition.coordinate().type() == QGeoCoordinate::Coordinate3D); double altitude = coord.altitude(); - double accuracy = geoPosition.hasAttribute(QGeoPositionInfo::HorizontalAccuracy) ? - geoPosition.attribute(QGeoPositionInfo::HorizontalAccuracy) : 0.0; + double accuracy = geoPosition.attribute(QGeoPositionInfo::HorizontalAccuracy); bool providesAltitudeAccuracy = geoPosition.hasAttribute(QGeoPositionInfo::VerticalAccuracy); - double altitudeAccuracy = providesAltitudeAccuracy ? geoPosition.attribute(QGeoPositionInfo::VerticalAccuracy) : 0.0; + double altitudeAccuracy = geoPosition.attribute(QGeoPositionInfo::VerticalAccuracy); bool providesHeading = geoPosition.hasAttribute(QGeoPositionInfo::Direction); - double heading = providesHeading ? geoPosition.attribute(QGeoPositionInfo::Direction) : 0.0; + double heading = geoPosition.attribute(QGeoPositionInfo::Direction); bool providesSpeed = geoPosition.hasAttribute(QGeoPositionInfo::GroundSpeed); - double speed = providesSpeed ? geoPosition.attribute(QGeoPositionInfo::GroundSpeed) : 0.0; + double speed = geoPosition.attribute(QGeoPositionInfo::GroundSpeed); RefPtr<Coordinates> coordinates = Coordinates::create(latitude, longitude, providesAltitude, altitude, accuracy, providesAltitudeAccuracy, altitudeAccuracy, diff --git a/WebCore/platform/qt/RenderThemeQt.cpp b/WebCore/platform/qt/RenderThemeQt.cpp index deb9037..22d99a1 100644 --- a/WebCore/platform/qt/RenderThemeQt.cpp +++ b/WebCore/platform/qt/RenderThemeQt.cpp @@ -58,8 +58,6 @@ #include "ScrollbarThemeQt.h" #include "TimeRanges.h" #include "UserAgentStyleSheets.h" -#include "qwebpage.h" - #include <QApplication> #include <QColor> diff --git a/WebCore/platform/qt/WidgetQt.cpp b/WebCore/platform/qt/WidgetQt.cpp index 00a58a4..0903b6e 100644 --- a/WebCore/platform/qt/WidgetQt.cpp +++ b/WebCore/platform/qt/WidgetQt.cpp @@ -41,14 +41,11 @@ #include "QWebPageClient.h" #include "ScrollView.h" -#include "qwebframe.h" -#include "qwebframe_p.h" -#include "qwebpage.h" - #include <QCoreApplication> #include <QDebug> #include <QPaintEngine> #include <QPainter> +#include <QWidget> namespace WebCore { diff --git a/WebCore/platform/text/LineEnding.cpp b/WebCore/platform/text/LineEnding.cpp new file mode 100644 index 0000000..545f22b --- /dev/null +++ b/WebCore/platform/text/LineEnding.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "LineEnding.h" + +#include "PlatformString.h" +#include <wtf/text/CString.h> + +namespace WebCore { + +// Normalize all line-endings to CRLF. +CString normalizeLineEndingsToCRLF(const CString& from) +{ + unsigned newLen = 0; + const char* p = from.data(); + while (char c = *p++) { + if (c == '\r') { + // Safe to look ahead because of trailing '\0'. + if (*p != '\n') { + // Turn CR into CRLF. + newLen += 2; + } + } else if (c == '\n') { + // Turn LF into CRLF. + newLen += 2; + } else { + // Leave other characters alone. + newLen += 1; + } + } + if (newLen == from.length()) + return from; + + // Make a copy of the string. + p = from.data(); + char* q; + CString result = CString::newUninitialized(newLen, q); + while (char c = *p++) { + if (c == '\r') { + // Safe to look ahead because of trailing '\0'. + if (*p != '\n') { + // Turn CR into CRLF. + *q++ = '\r'; + *q++ = '\n'; + } + } else if (c == '\n') { + // Turn LF into CRLF. + *q++ = '\r'; + *q++ = '\n'; + } else { + // Leave other characters alone. + *q++ = c; + } + } + return result; +} + +// Normalize all line-endings to CR or LF. +static CString normalizeToCROrLF(const CString& from, bool toCR) +{ + unsigned newLen = 0; + bool needFix = false; + const char* p = from.data(); + char fromEndingChar = toCR ? '\n' : '\r'; + char toEndingChar = toCR ? '\r' : '\n'; + while (char c = *p++) { + if (c == '\r' && *p == '\n') { + // Turn CRLF into CR or LF. + p++; + needFix = true; + } else if (c == fromEndingChar) { + // Turn CR/LF into LF/CR. + needFix = true; + } + newLen += 1; + } + if (!needFix) + return from; + + // Make a copy of the string. + p = from.data(); + char* q; + CString result = CString::newUninitialized(newLen, q); + while (char c = *p++) { + if (c == '\r' && *p == '\n') { + // Turn CRLF or CR into CR or LF. + p++; + *q++ = toEndingChar; + } else if (c == fromEndingChar) { + // Turn CR/LF into LF/CR. + *q++ = toEndingChar; + } else { + // Leave other characters alone. + *q++ = c; + } + } + return result; +} + +// Normalize all line-endings to CR. +CString normalizeLineEndingsToCR(const CString& from) +{ + return normalizeToCROrLF(from, true); +} + +// Normalize all line-endings to LF. +CString normalizeLineEndingsToLF(const CString& from) +{ + return normalizeToCROrLF(from, false); +} + +CString normalizeLineEndingsToNative(const CString& from) +{ +#if OS(WINDOWS) + return normalizeLineEndingsToCRLF(from); +#else + return normalizeLineEndingsToLF(from); +#endif +} + +} // namespace WebCore diff --git a/WebCore/platform/text/LineEnding.h b/WebCore/platform/text/LineEnding.h new file mode 100644 index 0000000..9c3e2aa --- /dev/null +++ b/WebCore/platform/text/LineEnding.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LineEnding_h +#define LineEnding_h + +namespace WTF { +class CString; +} + +namespace WebCore { + +// Normalize all line-endings in the given string to CRLF. +WTF::CString normalizeLineEndingsToCRLF(const WTF::CString&); + +// Normalize all line-endings in the given string to CR. +WTF::CString normalizeLineEndingsToCR(const WTF::CString&); + +// Normalize all line-endings in the given string to LF. +WTF::CString normalizeLineEndingsToLF(const WTF::CString&); + +// Normalize all line-endings in the given string to the native line-endings. +// (Normalize to CRLF on Windows and normalize to LF on all other platforms.) +WTF::CString normalizeLineEndingsToNative(const WTF::CString&); + +} // namespace WebCore + +#endif // LineEnding_h diff --git a/WebCore/platform/win/ClipboardUtilitiesWin.cpp b/WebCore/platform/win/ClipboardUtilitiesWin.cpp index fbd0011..e6af7ef 100644 --- a/WebCore/platform/win/ClipboardUtilitiesWin.cpp +++ b/WebCore/platform/win/ClipboardUtilitiesWin.cpp @@ -32,10 +32,10 @@ #include "TextEncoding.h" #include "markup.h" #include <CoreFoundation/CoreFoundation.h> +#include <shlwapi.h> +#include <wininet.h> // for INTERNET_MAX_URL_LENGTH #include <wtf/RetainPtr.h> #include <wtf/text/CString.h> -#include <shlwapi.h> -#include <wininet.h> // for INTERNET_MAX_URL_LENGTH namespace WebCore { @@ -97,7 +97,7 @@ static String extractURL(const String &inURL, String* title) return url; } -//Firefox text/html +// Firefox text/html static FORMATETC* texthtmlFormat() { static UINT cf = RegisterClipboardFormat(L"text/html"); @@ -109,7 +109,7 @@ HGLOBAL createGlobalData(const KURL& url, const String& title) { String mutableURL(url.string()); String mutableTitle(title); - SIZE_T size = mutableURL.length() + mutableTitle.length() + 2; // +1 for "\n" and +1 for null terminator + SIZE_T size = mutableURL.length() + mutableTitle.length() + 2; // +1 for "\n" and +1 for null terminator HGLOBAL cbData = ::GlobalAlloc(GPTR, size * sizeof(UChar)); if (cbData) { @@ -155,7 +155,7 @@ static void append(Vector<char>& vector, const CString& string) } // Documentation for the CF_HTML format is available at http://msdn.microsoft.com/workshop/networking/clipboard/htmlclipboard.asp -void markupToCF_HTML(const String& markup, const String& srcURL, Vector<char>& result) +void markupToCFHTML(const String& markup, const String& srcURL, Vector<char>& result) { if (markup.isEmpty()) return; @@ -256,7 +256,7 @@ FORMATETC* filenameFormat() return &urlFormat; } -//MSIE HTML Format +// MSIE HTML Format FORMATETC* htmlFormat() { static UINT cf = RegisterClipboardFormat(L"HTML Format"); @@ -294,18 +294,17 @@ String getURL(IDataObject* dataObject, DragData::FilenameConversionPolicy filena STGMEDIUM store; String url; success = false; - if (getWebLocData(dataObject, url, title)) { + if (getWebLocData(dataObject, url, title)) success = true; - return url; - } else if (SUCCEEDED(dataObject->GetData(urlWFormat(), &store))) { - //URL using unicode + else if (SUCCEEDED(dataObject->GetData(urlWFormat(), &store))) { + // URL using Unicode UChar* data = (UChar*)GlobalLock(store.hGlobal); url = extractURL(String(data), title); GlobalUnlock(store.hGlobal); ReleaseStgMedium(&store); success = true; } else if (SUCCEEDED(dataObject->GetData(urlFormat(), &store))) { - //URL using ascii + // URL using ASCII char* data = (char*)GlobalLock(store.hGlobal); url = extractURL(String(data), title); GlobalUnlock(store.hGlobal); @@ -349,14 +348,14 @@ String getPlainText(IDataObject* dataObject, bool& success) String text; success = false; if (SUCCEEDED(dataObject->GetData(plainTextWFormat(), &store))) { - //unicode text + // Unicode text UChar* data = (UChar*)GlobalLock(store.hGlobal); text = String(data); GlobalUnlock(store.hGlobal); ReleaseStgMedium(&store); success = true; } else if (SUCCEEDED(dataObject->GetData(plainTextFormat(), &store))) { - //ascii text + // ASCII text char* data = (char*)GlobalLock(store.hGlobal); text = String(data); GlobalUnlock(store.hGlobal); @@ -372,40 +371,55 @@ String getPlainText(IDataObject* dataObject, bool& success) return text; } +String getTextHTML(IDataObject* data, bool& success) +{ + STGMEDIUM store; + String html; + success = false; + if (SUCCEEDED(data->GetData(texthtmlFormat(), &store))) { + UChar* data = static_cast<UChar*>(GlobalLock(store.hGlobal)); + html = String(data); + GlobalUnlock(store.hGlobal); + ReleaseStgMedium(&store); + success = true; + } + return html; +} + PassRefPtr<DocumentFragment> fragmentFromFilenames(Document*, const IDataObject*) { - //FIXME: We should be able to create fragments from files + // FIXME: We should be able to create fragments from files return 0; } bool containsFilenames(const IDataObject*) { - //FIXME: We'll want to update this once we can produce fragments from files + // FIXME: We'll want to update this once we can produce fragments from files return false; } -//Convert a String containing CF_HTML formatted text to a DocumentFragment -PassRefPtr<DocumentFragment> fragmentFromCF_HTML(Document* doc, const String& cf_html) +// Convert a String containing CF_HTML formatted text to a DocumentFragment +PassRefPtr<DocumentFragment> fragmentFromCFHTML(Document* doc, const String& cfhtml) { // obtain baseURL if present String srcURLStr("sourceURL:"); String srcURL; - unsigned lineStart = cf_html.find(srcURLStr, 0, false); + unsigned lineStart = cfhtml.find(srcURLStr, 0, false); if (lineStart != -1) { - unsigned srcEnd = cf_html.find("\n", lineStart, false); + unsigned srcEnd = cfhtml.find("\n", lineStart, false); unsigned srcStart = lineStart+srcURLStr.length(); - String rawSrcURL = cf_html.substring(srcStart, srcEnd-srcStart); + String rawSrcURL = cfhtml.substring(srcStart, srcEnd-srcStart); replaceNBSPWithSpace(rawSrcURL); srcURL = rawSrcURL.stripWhiteSpace(); } // find the markup between "<!--StartFragment -->" and "<!--EndFragment -->", accounting for browser quirks - unsigned markupStart = cf_html.find("<html", 0, false); - unsigned tagStart = cf_html.find("startfragment", markupStart, false); - unsigned fragmentStart = cf_html.find('>', tagStart) + 1; - unsigned tagEnd = cf_html.find("endfragment", fragmentStart, false); - unsigned fragmentEnd = cf_html.reverseFind('<', tagEnd); - String markup = cf_html.substring(fragmentStart, fragmentEnd - fragmentStart).stripWhiteSpace(); + unsigned markupStart = cfhtml.find("<html", 0, false); + unsigned tagStart = cfhtml.find("startfragment", markupStart, false); + unsigned fragmentStart = cfhtml.find('>', tagStart) + 1; + unsigned tagEnd = cfhtml.find("endfragment", fragmentStart, false); + unsigned fragmentEnd = cfhtml.reverseFind('<', tagEnd); + String markup = cfhtml.substring(fragmentStart, fragmentEnd - fragmentStart).stripWhiteSpace(); return createFragmentFromMarkup(doc, markup, srcURL, FragmentScriptingNotAllowed); } @@ -420,23 +434,19 @@ PassRefPtr<DocumentFragment> fragmentFromHTML(Document* doc, IDataObject* data) String html; String srcURL; if (SUCCEEDED(data->GetData(htmlFormat(), &store))) { - //MS HTML Format parsing + // MS HTML Format parsing char* data = (char*)GlobalLock(store.hGlobal); SIZE_T dataSize = ::GlobalSize(store.hGlobal); - String cf_html(UTF8Encoding().decode(data, dataSize)); + String cfhtml(UTF8Encoding().decode(data, dataSize)); GlobalUnlock(store.hGlobal); ReleaseStgMedium(&store); - if (PassRefPtr<DocumentFragment> fragment = fragmentFromCF_HTML(doc, cf_html)) + if (PassRefPtr<DocumentFragment> fragment = fragmentFromCFHTML(doc, cfhtml)) return fragment; } - if (SUCCEEDED(data->GetData(texthtmlFormat(), &store))) { - //raw html - UChar* data = (UChar*)GlobalLock(store.hGlobal); - html = String(data); - GlobalUnlock(store.hGlobal); - ReleaseStgMedium(&store); + bool success = false; + html = getTextHTML(data, success); + if (success) return createFragmentFromMarkup(doc, html, srcURL, FragmentScriptingNotAllowed); - } return 0; } diff --git a/WebCore/platform/win/ClipboardUtilitiesWin.h b/WebCore/platform/win/ClipboardUtilitiesWin.h index ac5efd8..4ca46f9 100644 --- a/WebCore/platform/win/ClipboardUtilitiesWin.h +++ b/WebCore/platform/win/ClipboardUtilitiesWin.h @@ -49,7 +49,7 @@ FORMATETC* htmlFormat(); FORMATETC* cfHDropFormat(); FORMATETC* smartPasteFormat(); -void markupToCF_HTML(const String& markup, const String& srcURL, Vector<char>& result); +void markupToCFHTML(const String& markup, const String& srcURL, Vector<char>& result); void replaceNewlinesWithWindowsStyleNewlines(String&); void replaceNBSPWithSpace(String&); @@ -59,12 +59,12 @@ bool containsHTML(IDataObject*); PassRefPtr<DocumentFragment> fragmentFromFilenames(Document*, const IDataObject*); PassRefPtr<DocumentFragment> fragmentFromHTML(Document*, IDataObject*); -PassRefPtr<DocumentFragment> fragmentFromCF_HTML(Document*, const String& cf_html); +PassRefPtr<DocumentFragment> fragmentFromCFHTML(Document*, const String& cfhtml); String getURL(IDataObject*, DragData::FilenameConversionPolicy, bool& success, String* title = 0); String getPlainText(IDataObject*, bool& success); +String getTextHTML(IDataObject*, bool& success); } // namespace WebCore #endif // ClipboardUtilitiesWin_h - diff --git a/WebCore/platform/win/ClipboardWin.cpp b/WebCore/platform/win/ClipboardWin.cpp index 3c3a205..2cd6feb 100644 --- a/WebCore/platform/win/ClipboardWin.cpp +++ b/WebCore/platform/win/ClipboardWin.cpp @@ -105,9 +105,8 @@ static inline void pathRemoveBadFSCharacters(PWSTR psz, size_t length) size_t readFrom = 0; while (readFrom < length) { UINT type = PathGetCharType(psz[readFrom]); - if (psz[readFrom] == 0 || type & (GCT_LFNCHAR | GCT_SHORTCHAR)) { + if (!psz[readFrom] || type & (GCT_LFNCHAR | GCT_SHORTCHAR)) psz[writeTo++] = psz[readFrom]; - } readFrom++; } @@ -215,7 +214,7 @@ static HGLOBAL createGlobalImageFileContent(SharedBuffer* data) static HGLOBAL createGlobalHDropContent(const KURL& url, String& fileName, SharedBuffer* data) { - if (fileName.isEmpty() || !data ) + if (fileName.isEmpty() || !data) return 0; WCHAR filePath[MAX_PATH]; @@ -290,7 +289,7 @@ static HGLOBAL createGlobalUrlFileDescriptor(const String& url, const String& ti fgd->cItems = 1; fgd->fgd[0].dwFlags = FD_FILESIZE; int fileSize = ::WideCharToMultiByte(CP_ACP, 0, url.characters(), url.length(), 0, 0, 0, 0); - fileSize += strlen(szShellDotUrlTemplate) - 2; // -2 is for getting rid of %s in the template string + fileSize += strlen(szShellDotUrlTemplate) - 2; // -2 is for getting rid of %s in the template string fgd->fgd[0].nFileSizeLow = fileSize; estimatedSize = fileSize; fsPath = filesystemPathFromUrlOrTitle(url, title, L".URL", true); @@ -437,7 +436,7 @@ static bool writeURL(WCDataObject *data, const KURL& url, String title, bool wit if (withHTML) { Vector<char> cfhtmlData; - markupToCF_HTML(urlToMarkup(url, title), "", cfhtmlData); + markupToCFHTML(urlToMarkup(url, title), "", cfhtmlData); medium.hGlobal = createGlobalData(cfhtmlData); if (medium.hGlobal && FAILED(data->SetData(htmlFormat(), &medium, TRUE))) ::GlobalFree(medium.hGlobal); @@ -458,7 +457,7 @@ static bool writeURL(WCDataObject *data, const KURL& url, String title, bool wit void ClipboardWin::clearData(const String& type) { - //FIXME: Need to be able to write to the system clipboard <rdar://problem/5015941> + // FIXME: Need to be able to write to the system clipboard <rdar://problem/5015941> ASSERT(isForDragging()); if (policy() != ClipboardWritable || !m_writableDataObject) return; @@ -478,7 +477,7 @@ void ClipboardWin::clearData(const String& type) void ClipboardWin::clearAllData() { - //FIXME: Need to be able to write to the system clipboard <rdar://problem/5015941> + // FIXME: Need to be able to write to the system clipboard <rdar://problem/5015941> ASSERT(isForDragging()); if (policy() != ClipboardWritable) return; @@ -491,14 +490,13 @@ void ClipboardWin::clearAllData() String ClipboardWin::getData(const String& type, bool& success) const { success = false; - if (policy() != ClipboardReadable || !m_dataObject) { + if (policy() != ClipboardReadable || !m_dataObject) return ""; - } ClipboardDataType dataType = clipboardTypeFromMIMEType(type); if (dataType == ClipboardDataTypeText) return getPlainText(m_dataObject.get(), success); - else if (dataType == ClipboardDataTypeURL) + if (dataType == ClipboardDataTypeURL) return getURL(m_dataObject.get(), DragData::DoNotConvertFilenames, success); return ""; @@ -568,9 +566,8 @@ HashSet<String> ClipboardWin::types() const FORMATETC data; // IEnumFORMATETC::Next returns S_FALSE if there are no more items. - while (itr->Next(1, &data, 0) == S_OK) { + while (itr->Next(1, &data, 0) == S_OK) addMimeTypesForFormat(results, data); - } return results; } @@ -720,7 +717,7 @@ void ClipboardWin::declareAndWriteDragImage(Element* element, const KURL& url, c // Put img tag on the clipboard referencing the image Vector<char> data; - markupToCF_HTML(imageToMarkup(fullURL), "", data); + markupToCFHTML(imageToMarkup(fullURL), "", data); medium.hGlobal = createGlobalData(data); if (medium.hGlobal && FAILED(m_writableDataObject->SetData(htmlFormat(), &medium, TRUE))) ::GlobalFree(medium.hGlobal); @@ -757,7 +754,7 @@ void ClipboardWin::writeRange(Range* selectedRange, Frame* frame) ExceptionCode ec = 0; Vector<char> data; - markupToCF_HTML(createMarkup(selectedRange, 0, AnnotateForInterchange), + markupToCFHTML(createMarkup(selectedRange, 0, AnnotateForInterchange), selectedRange->startContainer(ec)->document()->url().string(), data); medium.hGlobal = createGlobalData(data); if (medium.hGlobal && FAILED(m_writableDataObject->SetData(htmlFormat(), &medium, TRUE))) diff --git a/WebCore/platform/win/ClipboardWin.h b/WebCore/platform/win/ClipboardWin.h index 49fdcfe..1b139ed 100644 --- a/WebCore/platform/win/ClipboardWin.h +++ b/WebCore/platform/win/ClipboardWin.h @@ -26,66 +26,66 @@ #ifndef ClipboardWin_h #define ClipboardWin_h +#include "COMPtr.h" #include "CachedResourceClient.h" #include "Clipboard.h" -#include "COMPtr.h" struct IDataObject; namespace WebCore { - class CachedImage; - class IntPoint; - class WCDataObject; - - // State available during IE's events for drag and drop and copy/paste - class ClipboardWin : public Clipboard, public CachedResourceClient { - public: - static PassRefPtr<ClipboardWin> create(bool isForDragging, IDataObject* dataObject, ClipboardAccessPolicy policy) - { - return adoptRef(new ClipboardWin(isForDragging, dataObject, policy)); - } - static PassRefPtr<ClipboardWin> create(bool isForDragging, WCDataObject* dataObject, ClipboardAccessPolicy policy) - { - return adoptRef(new ClipboardWin(isForDragging, dataObject, policy)); - } - ~ClipboardWin(); - - void clearData(const String& type); - void clearAllData(); - String getData(const String& type, bool& success) const; - bool setData(const String& type, const String& data); - - // extensions beyond IE's API - virtual HashSet<String> types() const; - virtual PassRefPtr<FileList> files() const; - - void setDragImage(CachedImage*, const IntPoint&); - void setDragImageElement(Node*, const IntPoint&); - - virtual DragImageRef createDragImage(IntPoint& dragLoc) const; - virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*); - virtual void writeURL(const KURL&, const String&, Frame*); - virtual void writeRange(Range*, Frame*); - virtual void writePlainText(const String&); - - virtual bool hasData(); - - COMPtr<IDataObject> dataObject() { return m_dataObject; } - - void setExternalDataObject(IDataObject *dataObject); - - private: - ClipboardWin(bool isForDragging, IDataObject*, ClipboardAccessPolicy); - ClipboardWin(bool isForDragging, WCDataObject*, ClipboardAccessPolicy); - - void resetFromClipboard(); - void setDragImage(CachedImage*, Node*, const IntPoint&); - - COMPtr<IDataObject> m_dataObject; - COMPtr<WCDataObject> m_writableDataObject; - Frame* m_frame; - }; +class CachedImage; +class IntPoint; +class WCDataObject; + +// State available during IE's events for drag and drop and copy/paste +class ClipboardWin : public Clipboard, public CachedResourceClient { +public: + static PassRefPtr<ClipboardWin> create(bool isForDragging, IDataObject* dataObject, ClipboardAccessPolicy policy) + { + return adoptRef(new ClipboardWin(isForDragging, dataObject, policy)); + } + static PassRefPtr<ClipboardWin> create(bool isForDragging, WCDataObject* dataObject, ClipboardAccessPolicy policy) + { + return adoptRef(new ClipboardWin(isForDragging, dataObject, policy)); + } + ~ClipboardWin(); + + void clearData(const String& type); + void clearAllData(); + String getData(const String& type, bool& success) const; + bool setData(const String& type, const String& data); + + // extensions beyond IE's API + virtual HashSet<String> types() const; + virtual PassRefPtr<FileList> files() const; + + void setDragImage(CachedImage*, const IntPoint&); + void setDragImageElement(Node*, const IntPoint&); + + virtual DragImageRef createDragImage(IntPoint& dragLoc) const; + virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*); + virtual void writeURL(const KURL&, const String&, Frame*); + virtual void writeRange(Range*, Frame*); + virtual void writePlainText(const String&); + + virtual bool hasData(); + + COMPtr<IDataObject> dataObject() { return m_dataObject; } + + void setExternalDataObject(IDataObject *dataObject); + +private: + ClipboardWin(bool isForDragging, IDataObject*, ClipboardAccessPolicy); + ClipboardWin(bool isForDragging, WCDataObject*, ClipboardAccessPolicy); + + void resetFromClipboard(); + void setDragImage(CachedImage*, Node*, const IntPoint&); + + COMPtr<IDataObject> m_dataObject; + COMPtr<WCDataObject> m_writableDataObject; + Frame* m_frame; +}; } // namespace WebCore diff --git a/WebCore/platform/win/CursorWin.cpp b/WebCore/platform/win/CursorWin.cpp index 22a535d..2dd1452 100644 --- a/WebCore/platform/win/CursorWin.cpp +++ b/WebCore/platform/win/CursorWin.cpp @@ -39,11 +39,6 @@ namespace WebCore { -Cursor::Cursor(const Cursor& other) - : m_impl(other.m_impl) -{ -} - static inline bool supportsAlphaCursors() { OSVERSIONINFO osinfo = {0}; @@ -52,8 +47,10 @@ static inline bool supportsAlphaCursors() return osinfo.dwMajorVersion > 5 || (osinfo.dwMajorVersion == 5 && osinfo.dwMinorVersion > 0); } -Cursor::Cursor(Image* img, const IntPoint& hotSpot) +static PassRefPtr<SharedCursor> createSharedCursor(Image* img, const IntPoint& hotSpot) { + RefPtr<SharedCursor> impl; + IntPoint effectiveHotSpot = determineHotSpot(img, hotSpot); static bool doAlpha = supportsAlphaCursors(); BitmapInfo cursorImage = BitmapInfo::create(IntSize(img->width(), img->height())); @@ -80,7 +77,7 @@ Cursor::Cursor(Image* img, const IntPoint& hotSpot) ii.hbmMask = hMask.get(); ii.hbmColor = hCursor.get(); - m_impl = SharedCursor::create(CreateIconIndirect(&ii)); + impl = SharedCursor::create(CreateIconIndirect(&ii)); } else { // Platform doesn't support alpha blended cursors, so we need // to create the mask manually @@ -115,303 +112,183 @@ Cursor::Cursor(Image* img, const IntPoint& hotSpot) icon.yHotspot = effectiveHotSpot.y(); icon.hbmMask = andMask.get(); icon.hbmColor = xorMask.get(); - m_impl = SharedCursor::create(CreateIconIndirect(&icon)); + impl = SharedCursor::create(CreateIconIndirect(&icon)); DeleteDC(xorMaskDC); DeleteDC(andMaskDC); } DeleteDC(workingDC); ReleaseDC(0, dc); -} -Cursor::~Cursor() -{ + return impl.release(); } -Cursor& Cursor::operator=(const Cursor& other) -{ - m_impl = other.m_impl; - return *this; -} - -Cursor::Cursor(PlatformCursor c) - : m_impl(c) +static PassRefPtr<SharedCursor> loadSharedCursor(HINSTANCE hInstance, LPCTSTR lpCursorName) { + return SharedCursor::create(::LoadCursor(hInstance, lpCursorName)); } -static Cursor loadCursorByName(char* name, int x, int y) +static PassRefPtr<SharedCursor> loadCursorByName(char* name, int x, int y) { IntPoint hotSpot(x, y); - Cursor c; RefPtr<Image> cursorImage(Image::loadPlatformResource(name)); - if (cursorImage && !cursorImage->isNull()) - c = Cursor(cursorImage.get(), hotSpot); - else - c = pointerCursor(); - return c; -} - -static PassRefPtr<SharedCursor> loadSharedCursor(HINSTANCE hInstance, LPCTSTR lpCursorName) -{ - return SharedCursor::create(LoadCursor(hInstance, lpCursorName)); -} - -const Cursor& pointerCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_ARROW); - return c; -} - -const Cursor& crossCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_CROSS); - return c; -} - -const Cursor& handCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_HAND); - return c; -} - -const Cursor& iBeamCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_IBEAM); - return c; -} - -const Cursor& waitCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_WAIT); - return c; -} - -const Cursor& helpCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_HELP); - return c; -} - -const Cursor& eastResizeCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_SIZEWE); - return c; -} - -const Cursor& northResizeCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_SIZENS); - return c; -} - -const Cursor& northEastResizeCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_SIZENESW); - return c; -} - -const Cursor& northWestResizeCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_SIZENWSE); - return c; -} - -const Cursor& southResizeCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_SIZENS); - return c; -} - -const Cursor& southEastResizeCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_SIZENWSE); - return c; -} - -const Cursor& southWestResizeCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_SIZENESW); - return c; -} - -const Cursor& westResizeCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_SIZEWE); - return c; -} - -const Cursor& northSouthResizeCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_SIZENS); - return c; -} - -const Cursor& eastWestResizeCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_SIZEWE); - return c; -} - -const Cursor& northEastSouthWestResizeCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_SIZENESW); - return c; -} - -const Cursor& northWestSouthEastResizeCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_SIZENWSE); - return c; -} - -const Cursor& columnResizeCursor() -{ - // FIXME: Windows does not have a standard column resize cursor <rdar://problem/5018591> - static Cursor c = loadSharedCursor(0, IDC_SIZEWE); - return c; -} - -const Cursor& rowResizeCursor() -{ - // FIXME: Windows does not have a standard row resize cursor <rdar://problem/5018591> - static Cursor c = loadSharedCursor(0, IDC_SIZENS); - return c; -} - -const Cursor& middlePanningCursor() -{ - static const Cursor c = loadCursorByName("panIcon", 8, 8); - return c; -} - -const Cursor& eastPanningCursor() -{ - static const Cursor c = loadCursorByName("panEastCursor", 7, 7); - return c; -} - -const Cursor& northPanningCursor() -{ - static const Cursor c = loadCursorByName("panNorthCursor", 7, 7); - return c; -} - -const Cursor& northEastPanningCursor() -{ - static const Cursor c = loadCursorByName("panNorthEastCursor", 7, 7); - return c; -} - -const Cursor& northWestPanningCursor() -{ - static const Cursor c = loadCursorByName("panNorthWestCursor", 7, 7); - return c; -} - -const Cursor& southPanningCursor() -{ - static const Cursor c = loadCursorByName("panSouthCursor", 7, 7); - return c; -} - -const Cursor& southEastPanningCursor() -{ - static const Cursor c = loadCursorByName("panSouthEastCursor", 7, 7); - return c; -} - -const Cursor& southWestPanningCursor() -{ - static const Cursor c = loadCursorByName("panSouthWestCursor", 7, 7); - return c; -} - -const Cursor& westPanningCursor() -{ - static const Cursor c = loadCursorByName("panWestCursor", 7, 7); - return c; -} - -const Cursor& moveCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_SIZEALL); - return c; -} - -const Cursor& verticalTextCursor() -{ - static const Cursor c = loadCursorByName("verticalTextCursor", 7, 7); - return c; -} - -const Cursor& cellCursor() -{ - return pointerCursor(); -} - -const Cursor& contextMenuCursor() -{ - return pointerCursor(); -} - -const Cursor& aliasCursor() -{ - return pointerCursor(); -} - -const Cursor& progressCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_APPSTARTING); - return c; -} - -const Cursor& noDropCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_NO); - return c; -} - -const Cursor& copyCursor() -{ - return pointerCursor(); -} - -const Cursor& noneCursor() -{ - return pointerCursor(); -} - -const Cursor& notAllowedCursor() -{ - static Cursor c = loadSharedCursor(0, IDC_NO); - return c; -} - -const Cursor& zoomInCursor() -{ - static const Cursor c = loadCursorByName("zoomInCursor", 7, 7); - return c; + if (cursorImage && !cursorImage->isNull()) + return createSharedCursor(cursorImage.get(), hotSpot); + return loadSharedCursor(0, IDC_ARROW); +} + +void Cursor::ensurePlatformCursor() const +{ + if (m_platformCursor) + return; + + switch (m_type) { + case Cursor::Pointer: + case Cursor::Cell: + case Cursor::ContextMenu: + case Cursor::Alias: + case Cursor::Copy: + case Cursor::None: + case Cursor::Grab: + case Cursor::Grabbing: + m_platformCursor = loadSharedCursor(0, IDC_ARROW); + break; + case Cursor::Cross: + m_platformCursor = loadSharedCursor(0, IDC_CROSS); + break; + case Cursor::Hand: + m_platformCursor = loadSharedCursor(0, IDC_HAND); + break; + case Cursor::IBeam: + m_platformCursor = loadSharedCursor(0, IDC_IBEAM); + break; + case Cursor::Wait: + m_platformCursor = loadSharedCursor(0, IDC_WAIT); + break; + case Cursor::Help: + m_platformCursor = loadSharedCursor(0, IDC_HELP); + break; + case Cursor::Move: + m_platformCursor = loadSharedCursor(0, IDC_SIZEALL); + break; + case Cursor::MiddlePanning: + m_platformCursor = loadCursorByName("panIcon", 8, 8); + break; + case Cursor::EastResize: + m_platformCursor = loadSharedCursor(0, IDC_SIZEWE); + break; + case Cursor::EastPanning: + m_platformCursor = loadCursorByName("panEastCursor", 7, 7); + break; + case Cursor::NorthResize: + m_platformCursor = loadSharedCursor(0, IDC_SIZENS); + break; + case Cursor::NorthPanning: + m_platformCursor = loadCursorByName("panNorthCursor", 7, 7); + break; + case Cursor::NorthEastResize: + m_platformCursor = loadSharedCursor(0, IDC_SIZENESW); + break; + case Cursor::NorthEastPanning: + m_platformCursor = loadCursorByName("panNorthEastCursor", 7, 7); + break; + case Cursor::NorthWestResize: + m_platformCursor = loadSharedCursor(0, IDC_SIZENWSE); + break; + case Cursor::NorthWestPanning: + m_platformCursor = loadCursorByName("panNorthWestCursor", 7, 7); + break; + case Cursor::SouthResize: + m_platformCursor = loadSharedCursor(0, IDC_SIZENS); + break; + case Cursor::SouthPanning: + m_platformCursor = loadCursorByName("panSouthCursor", 7, 7); + break; + case Cursor::SouthEastResize: + m_platformCursor = loadSharedCursor(0, IDC_SIZENWSE); + break; + case Cursor::SouthEastPanning: + m_platformCursor = loadCursorByName("panSouthEastCursor", 7, 7); + break; + case Cursor::SouthWestResize: + m_platformCursor = loadSharedCursor(0, IDC_SIZENESW); + break; + case Cursor::SouthWestPanning: + m_platformCursor = loadCursorByName("panSouthWestCursor", 7, 7); + break; + case Cursor::WestResize: + m_platformCursor = loadSharedCursor(0, IDC_SIZEWE); + break; + case Cursor::NorthSouthResize: + m_platformCursor = loadSharedCursor(0, IDC_SIZENS); + break; + case Cursor::EastWestResize: + m_platformCursor = loadSharedCursor(0, IDC_SIZEWE); + break; + case Cursor::WestPanning: + m_platformCursor = loadCursorByName("panWestCursor", 7, 7); + break; + case Cursor::NorthEastSouthWestResize: + m_platformCursor = loadSharedCursor(0, IDC_SIZENESW); + break; + case Cursor::NorthWestSouthEastResize: + m_platformCursor = loadSharedCursor(0, IDC_SIZENWSE); + break; + case Cursor::ColumnResize: + // FIXME: Windows does not have a standard column resize cursor <rdar://problem/5018591> + m_platformCursor = loadSharedCursor(0, IDC_SIZEWE); + break; + case Cursor::RowResize: + // FIXME: Windows does not have a standard row resize cursor <rdar://problem/5018591> + m_platformCursor = loadSharedCursor(0, IDC_SIZENS); + break; + case Cursor::VerticalText: + m_platformCursor = loadCursorByName("verticalTextCursor", 7, 7); + break; + case Cursor::Progress: + m_platformCursor = loadSharedCursor(0, IDC_APPSTARTING); + break; + case Cursor::NoDrop: + break; + case Cursor::NotAllowed: + m_platformCursor = loadSharedCursor(0, IDC_NO); + break; + case Cursor::ZoomIn: + m_platformCursor = loadCursorByName("zoomInCursor", 7, 7); + break; + case Cursor::ZoomOut: + m_platformCursor = loadCursorByName("zoomOutCursor", 7, 7); + break; + case Cursor::Custom: + m_platformCursor = createSharedCursor(m_image.get(), m_hotSpot); + break; + } } -const Cursor& zoomOutCursor() +SharedCursor::~SharedCursor() { - static const Cursor c = loadCursorByName("zoomOutCursor", 7, 7); - return c; + DestroyIcon(m_nativeCursor); } -const Cursor& grabCursor() +Cursor::Cursor(const Cursor& other) + : m_type(other.m_type) + , m_image(other.m_image) + , m_hotSpot(other.m_hotSpot) + , m_platformCursor(other.m_platformCursor) { - return pointerCursor(); } -const Cursor& grabbingCursor() +Cursor& Cursor::operator=(const Cursor& other) { - return pointerCursor(); + m_type = other.m_type; + m_image = other.m_image; + m_hotSpot = other.m_hotSpot; + m_platformCursor = other.m_platformCursor; + return *this; } -SharedCursor::~SharedCursor() +Cursor::~Cursor() { - DestroyIcon(m_nativeCursor); } -} +} // namespace WebCore diff --git a/WebCore/platform/win/PasteboardWin.cpp b/WebCore/platform/win/PasteboardWin.cpp index 512f6cf..808c863 100644 --- a/WebCore/platform/win/PasteboardWin.cpp +++ b/WebCore/platform/win/PasteboardWin.cpp @@ -54,7 +54,7 @@ static LRESULT CALLBACK PasteboardOwnerWndProc(HWND hWnd, UINT message, WPARAM w LRESULT lresult = 0; LONG_PTR longPtr = GetWindowLongPtr(hWnd, 0); - switch(message) { + switch (message) { case WM_RENDERFORMAT: // This message comes when SetClipboardData was sent a null data handle // and now it's come time to put the data on the clipboard. @@ -117,7 +117,7 @@ void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, if (::OpenClipboard(m_owner)) { ExceptionCode ec = 0; Vector<char> data; - markupToCF_HTML(createMarkup(selectedRange, 0, AnnotateForInterchange), + markupToCFHTML(createMarkup(selectedRange, 0, AnnotateForInterchange), selectedRange->startContainer(ec)->document()->url().string(), data); HGLOBAL cbData = createGlobalData(data); if (!::SetClipboardData(HTMLClipboardFormat, cbData)) @@ -139,7 +139,7 @@ void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, // enable smart-replacing later on by putting dummy data on the pasteboard if (canSmartCopyOrDelete) { if (::OpenClipboard(m_owner)) { - ::SetClipboardData(WebSmartPasteFormat, NULL); + ::SetClipboardData(WebSmartPasteFormat, 0); ::CloseClipboard(); } @@ -185,7 +185,7 @@ void Pasteboard::writeURL(const KURL& url, const String& titleStr, Frame* frame) // write to clipboard in format CF_HTML to be able to paste into contenteditable areas as a link if (::OpenClipboard(m_owner)) { Vector<char> data; - markupToCF_HTML(urlToMarkup(url, title), "", data); + markupToCFHTML(urlToMarkup(url, title), "", data); HGLOBAL cbData = createGlobalData(data); if (!::SetClipboardData(HTMLClipboardFormat, cbData)) ::GlobalFree(cbData); @@ -260,8 +260,8 @@ String Pasteboard::plainText(Frame* frame) ::GlobalUnlock(cbData); ::CloseClipboard(); return fromClipboard; - } else - ::CloseClipboard(); + } + ::CloseClipboard(); } if (::IsClipboardFormatAvailable(CF_TEXT) && ::OpenClipboard(m_owner)) { @@ -272,8 +272,8 @@ String Pasteboard::plainText(Frame* frame) ::GlobalUnlock(cbData); ::CloseClipboard(); return fromClipboard; - } else - ::CloseClipboard(); + } + ::CloseClipboard(); } return String(); @@ -288,11 +288,11 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP HANDLE cbData = ::GetClipboardData(HTMLClipboardFormat); if (cbData) { SIZE_T dataSize = ::GlobalSize(cbData); - String cf_html(UTF8Encoding().decode((char*)::GlobalLock(cbData), dataSize)); + String cfhtml(UTF8Encoding().decode((char*)::GlobalLock(cbData), dataSize)); ::GlobalUnlock(cbData); ::CloseClipboard(); - PassRefPtr<DocumentFragment> fragment = fragmentFromCF_HTML(frame->document(), cf_html); + PassRefPtr<DocumentFragment> fragment = fragmentFromCFHTML(frame->document(), cfhtml); if (fragment) return fragment; } else @@ -306,7 +306,7 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP if (cbData) { UChar* buffer = (UChar*)GlobalLock(cbData); String str(buffer); - ::GlobalUnlock( cbData ); + ::GlobalUnlock(cbData); ::CloseClipboard(); RefPtr<DocumentFragment> fragment = createFragmentFromText(context.get(), str); if (fragment) @@ -323,7 +323,7 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP if (cbData) { char* buffer = (char*)GlobalLock(cbData); String str(buffer); - ::GlobalUnlock( cbData ); + ::GlobalUnlock(cbData); ::CloseClipboard(); RefPtr<DocumentFragment> fragment = createFragmentFromText(context.get(), str); if (fragment) diff --git a/WebCore/platform/win/WidgetWin.cpp b/WebCore/platform/win/WidgetWin.cpp index 607c0d8..416260b 100644 --- a/WebCore/platform/win/WidgetWin.cpp +++ b/WebCore/platform/win/WidgetWin.cpp @@ -59,7 +59,6 @@ void Widget::hide() { } -HCURSOR lastSetCursor = 0; bool ignoreNextSetCursor = false; void Widget::setCursor(const Cursor& cursor) @@ -71,30 +70,10 @@ void Widget::setCursor(const Cursor& cursor) return; } - if (!cursor.impl()->nativeCursor()) - return; - - lastSetCursor = cursor.impl()->nativeCursor(); - ScrollView* view = root(); - if (!view || !view->isFrameView()) { - SetCursor(lastSetCursor); - return; - } - - Frame* frame = static_cast<FrameView*>(view)->frame(); - if (!frame) { - SetCursor(lastSetCursor); + if (!view) return; - } - - Page* page = frame->page(); - if (!page) { - SetCursor(lastSetCursor); - return; - } - - page->chrome()->setCursor(lastSetCursor); + view->hostWindow()->setCursor(cursor); } void Widget::paint(GraphicsContext*, const IntRect&) diff --git a/WebCore/platform/wince/CursorWince.cpp b/WebCore/platform/wince/CursorWince.cpp index e35f1f9..d7dcfb4 100644 --- a/WebCore/platform/wince/CursorWince.cpp +++ b/WebCore/platform/wince/CursorWince.cpp @@ -38,12 +38,12 @@ static const Cursor& getCursor(CursorType type) } Cursor::Cursor(const Cursor& other) -: m_impl(other.m_impl) +: m_platformCursor(other.m_platformCursor) { } Cursor::Cursor(Image* img, const IntPoint& hotspot) -: m_impl(CursorNone) +: m_platformCursor(CursorNone) { } @@ -53,12 +53,12 @@ Cursor::~Cursor() Cursor& Cursor::operator=(const Cursor& other) { - m_impl = other.m_impl; + m_platformCursor = other.m_platformCursor; return *this; } Cursor::Cursor(PlatformCursor c) -: m_impl(c) +: m_platformCursor(c) { } diff --git a/WebCore/platform/wx/CursorWx.cpp b/WebCore/platform/wx/CursorWx.cpp index ed7f86b..dd61f1e 100644 --- a/WebCore/platform/wx/CursorWx.cpp +++ b/WebCore/platform/wx/CursorWx.cpp @@ -34,15 +34,15 @@ namespace WebCore { Cursor::Cursor(const Cursor& other) - : m_impl(other.m_impl) + : m_platformCursor(other.m_platformCursor) { } Cursor::Cursor(Image* image, const IntPoint&) { - m_impl = 0; + m_platformCursor = 0; // FIXME: figure out why the below code causes a crash - //m_impl = new wxCursor( image->getWxBitmap()->ConvertToImage() ); + //m_platformCursor = new wxCursor( image->getWxBitmap()->ConvertToImage() ); } Cursor::~Cursor() @@ -51,12 +51,12 @@ Cursor::~Cursor() Cursor& Cursor::operator=(const Cursor& other) { - m_impl = other.m_impl; + m_platformCursor = other.m_platformCursor; return *this; } Cursor::Cursor(wxCursor* c) - : m_impl(c) + : m_platformCursor(c) { } |