+2004-09-20 Chris Blumenberg <cblu@apple.com>
+
+ Fixed:
+ <rdar://problem/3429921> obey PARAM tags inside of OBJECT tags when necessary
+ <rdar://problem/3515685> Object tag in Java 1.4.1 / Safari doesn't recognize params
+
+ Reviewed by darin.
+
+ * khtml/khtml_part.cpp:
+ (KHTMLPart::requestFrame): take 2 parameter arrays rather than 1 which will have to be parsed
+ (KHTMLPart::requestObject): ditto
+ * khtml/khtml_part.h:
+ * khtml/khtmlpart_p.h:
+ * khtml/rendering/render_frames.cpp:
+ (RenderPartObject::updateWidget): use PARAM tags when there is no EMBED specified
+ * kwq/KWQKHTMLPart.h:
+ * kwq/KWQKHTMLPart.mm:
+ (KWQKHTMLPart::createPart): call renamed bridge method
+ * kwq/KWQKJavaAppletWidget.mm:
+ (KJavaAppletWidget::KJavaAppletWidget): ditto
+ * kwq/KWQStringList.h:
+ * kwq/KWQStringList.mm:
+ (QStringList::getNSArray): return a const array
+ * kwq/WebCoreBridge.h:
+ * kwq/WebCoreBridge.mm:
+ (-[WebCoreBridge URLWithAttributeString:]): renamed to match API
+
2004-09-20 Darin Adler <darin@apple.com>
Reviewed by Ken.
#endif
bool KHTMLPart::requestFrame( khtml::RenderPart *frame, const QString &url, const QString &frameName,
- const QStringList ¶ms, bool isIFrame )
+ const QStringList ¶mNames, const QStringList ¶mValues, bool isIFrame )
{
// kdDebug( 6050 ) << "childRequest( ..., " << url << ", " << frameName << " )" << endl;
FrameIt it = d->m_frames.find( frameName );
(*it).m_type = isIFrame ? khtml::ChildFrame::IFrame : khtml::ChildFrame::Frame;
(*it).m_frame = frame;
- (*it).m_params = params;
+ (*it).m_paramValues = paramNames;
+ (*it).m_paramNames = paramValues;
// Support for <frame src="javascript:string">
if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
}
bool KHTMLPart::requestObject( khtml::RenderPart *frame, const QString &url, const QString &serviceType,
- const QStringList ¶ms )
+ const QStringList ¶mNames, const QStringList ¶mValues )
{
khtml::ChildFrame child;
QValueList<khtml::ChildFrame>::Iterator it = d->m_objects.append( child );
(*it).m_frame = frame;
(*it).m_type = khtml::ChildFrame::Object;
- (*it).m_params = params;
+ (*it).m_paramNames = paramNames;
+ (*it).m_paramValues = paramValues;
KURL completedURL;
if (!url.isEmpty())
QVariant executeScheduledScript();
bool requestFrame( khtml::RenderPart *frame, const QString &url, const QString &frameName,
- const QStringList &args = QStringList(), bool isIFrame = false );
+ const QStringList ¶mNames = QStringList(), const QStringList ¶mValues = QStringList(), bool isIFrame = false );
/**
* @internal returns a name for a frame without a name.
QString requestFrameName();
bool requestObject( khtml::RenderPart *frame, const QString &url, const QString &serviceType,
- const QStringList &args = QStringList() );
+ const QStringList ¶mNames = QStringList(), const QStringList ¶mValues = QStringList() );
bool requestObject( khtml::ChildFrame *child, const KURL &url, const KParts::URLArgs &args = KParts::URLArgs() );
bool m_bPreloaded;
KURL m_workingURL;
Type m_type;
- QStringList m_params;
+ QStringList m_paramNames;
+ QStringList m_paramValues;
bool m_bNotify;
};
#include <kglobal.h>
#include <qtimer.h>
#include <qpainter.h>
+#include "qdict.h"
using namespace khtml;
using namespace DOM;
{
QString url;
QString serviceType;
- QStringList params;
+ QStringList paramNames;
+ QStringList paramValues;
KHTMLPart *part = m_view->part();
setNeedsLayoutAndMinMaxRecalc();
serviceType = o->serviceType;
}
- // Then try the PARAM tags for the URL and type attributes.
+ QDict<bool> uniqueParamNames(5, false);
+
+ // Scan the PARAM children.
+ // Get the URL and type from the params if we don't already have them.
+ // Get the attributes from the params if there is no EMBED tag.
NodeImpl *child = o->firstChild();
- while (child && (url.isEmpty() || serviceType.isEmpty())) {
+ while (child && (url.isEmpty() || serviceType.isEmpty() || !embed)) {
if (child->id() == ID_PARAM) {
HTMLParamElementImpl *p = static_cast<HTMLParamElementImpl *>( child );
QString name = p->name().lower();
if (serviceType.isEmpty() && name == "type") {
serviceType = p->value();
}
-
+ if (!embed) {
+ bool dummyValue = true;
+ uniqueParamNames.insert(p->name(), &dummyValue);
+ paramNames.append(p->name());
+ paramValues.append(p->value());
+ }
}
child = child->nextSibling();
}
- // Lastly try to map a specific CLASSID to a type.
+ // Turn the attributes of either the EMBED tag or OBJECT tag into arrays, but don't override PARAM values.
+ NamedAttrMapImpl* attributes = embedOrObject->attributes();
+ if (attributes) {
+ for (unsigned long i = 0; i < attributes->length(); ++i) {
+ AttributeImpl* it = attributes->attributeItem(i);
+ QString name = o->getDocument()->attrName(it->id()).string();
+ if (embed || uniqueParamNames.find(name) == 0) {
+ paramNames.append(name);
+ paramValues.append(it->value().string());
+ }
+ }
+ }
+
+ // If we still don't have a type, try to map from a specific CLASSID to a type.
if (serviceType.isEmpty() && !o->classId.isEmpty()) {
+ // It is ActiveX, but the nsplugin system handling
+ // should also work, that's why we don't override the
+ // serviceType with application/x-activex-handler
+ // but let the KTrader in khtmlpart::createPart() detect
+ // the user's preference: launch with activex viewer or
+ // with nspluginviewer (Niko)
if (o->classId.contains("D27CDB6E-AE6D-11cf-96B8-444553540000")) {
- // It is ActiveX, but the nsplugin system handling
- // should also work, that's why we don't override the
- // serviceType with application/x-activex-handler
- // but let the KTrader in khtmlpart::createPart() detect
- // the user's preference: launch with activex viewer or
- // with nspluginviewer (Niko)
serviceType = "application/x-shockwave-flash";
- } else if(o->classId.contains("CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA")) {
+ } else if (o->classId.contains("CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA")) {
serviceType = "audio/x-pn-realaudio-plugin";
- } else if(o->classId.contains("02BF25D5-8C17-4B23-BC80-D3488ABDDC6B")) {
+ } else if (o->classId.contains("02BF25D5-8C17-4B23-BC80-D3488ABDDC6B")) {
serviceType = "video/quicktime";
- } else if(o->classId.contains("166B1BCA-3F9C-11CF-8075-444553540000")) {
+ } else if (o->classId.contains("166B1BCA-3F9C-11CF-8075-444553540000")) {
serviceType = "application/x-director";
} else {
// We have a clsid, means this is activex (Niko)
if (!url.isEmpty() && url == part->baseURL()) {
return;
}
-
- // Turn the attributes of either the EMBED tag or OBJECT tag into an array.
- NamedAttrMapImpl* attributes = embedOrObject->attributes();
- if (attributes) {
- for (unsigned long i = 0; i < attributes->length(); ++i) {
- AttributeImpl* it = attributes->attributeItem(i);
- params.append(o->getDocument()->attrName(it->id()).string() + "=\"" + it->value().string() + "\"");
- }
- }
-
+
+#if !APPLE_CHANGES
params.append( QString::fromLatin1("__KHTML__CLASSID=\"%1\"").arg( o->classId ) );
params.append( QString::fromLatin1("__KHTML__CODEBASE=\"%1\"").arg( o->getAttribute(ATTR_CODEBASE).string() ) );
-
- part->requestObject( this, url, serviceType, params );
+#endif
+
+ part->requestObject( this, url, serviceType, paramNames, paramValues );
} else if ( element()->id() == ID_EMBED ) {
HTMLEmbedElementImpl *o = static_cast<HTMLEmbedElementImpl *>(element());
if (a) {
for (unsigned long i = 0; i < a->length(); ++i) {
AttributeImpl* it = a->attributeItem(i);
- params.append(o->getDocument()->attrName(it->id()).string() + "=\"" + it->value().string() + "\"");
+ paramNames.append(o->getDocument()->attrName(it->id()).string());
+ paramValues.append(it->value().string());
}
}
- part->requestObject( this, url, serviceType, params );
+ part->requestObject( this, url, serviceType, paramNames, paramValues );
} else {
assert(element()->id() == ID_IFRAME);
HTMLIFrameElementImpl *o = static_cast<HTMLIFrameElementImpl *>(element());
return;
}
KHTMLView *v = static_cast<KHTMLView *>(m_view);
- bool requestSucceeded = v->part()->requestFrame( this, url, o->name.string(), QStringList(), true );
+ bool requestSucceeded = v->part()->requestFrame( this, url, o->name.string(), QStringList(), QStringList(), true );
if (requestSucceeded && url == "about:blank") {
KHTMLPart *newPart = v->part()->findFrame( o->name.string() );
if (newPart && newPart->xmlDocImpl()) {
void setStatusBarText(const QString &status);
void urlSelected(const KURL &url, int button, int state, const KParts::URLArgs &args);
- bool requestObject(khtml::RenderPart *frame, const QString &url, const QString &serviceType, const QStringList &args);
KParts::ReadOnlyPart *createPart(const khtml::ChildFrame &child, const KURL &url, const QString &mimeType);
void scheduleClose();
BOOL needFrame = [_bridge frameRequiredForMIMEType:mimeType.getNSString() URL:url.getNSURL()];
if (child.m_type == ChildFrame::Object && !needFrame) {
- NSMutableArray *attributesArray = [NSMutableArray arrayWithCapacity:child.m_params.count()];
- for (uint i = 0; i < child.m_params.count(); i++) {
- [attributesArray addObject:child.m_params[i].getNSString()];
- }
-
KWQPluginPart *newPart = new KWQPluginPart;
newPart->setWidget(new QWidget([_bridge viewForPluginWithURL:url.getNSURL()
- attributes:attributesArray
- baseURL:KURL(d->m_doc->baseURL()).getNSURL()
- MIMEType:child.m_args.serviceType.getNSString()]));
+ attributeNames:child.m_paramNames.getNSArray()
+ attributeValues:child.m_paramValues.getNSArray()
+ MIMEType:child.m_args.serviceType.getNSString()]));
part = newPart;
} else {
LOG(Frames, "name %s", child.m_name.ascii());
{
KWQ_BLOCK_EXCEPTIONS;
- NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init];
+ NSMutableArray *attributeNames = [[NSMutableArray alloc] init];
+ NSMutableArray *attributeValues = [[NSMutableArray alloc] init];
QMapConstIterator<QString, QString> it = args.begin();
QMapConstIterator<QString, QString> end = args.end();
QString baseURLString;
if (it.key().lower() == "baseurl") {
baseURLString = it.data();
}
- [attributes setObject:it.data().getNSString() forKey:it.key().getNSString()];
+ [attributeNames addObject:it.key().getNSString()];
+ [attributeValues addObject:it.data().getNSString()];
++it;
}
KWQKHTMLPart *part = KWQ(c->part());
setView([part->bridge() viewForJavaAppletWithFrame:NSMakeRect(0, 0, size.width(), size.height())
- attributes:attributes
+ attributeNames:attributeNames
+ attributeValues:attributeValues
baseURL:part->completeURL(baseURLString).getNSURL()]);
- [attributes release];
+ [attributeNames release];
+ [attributeValues release];
part->view()->addChild(this);
KWQ_UNBLOCK_EXCEPTIONS;
QString pop_front();
- NSArray *getNSArray();
+ NSArray *getNSArray() const;
};
#endif
return front;
}
-NSArray *QStringList::getNSArray()
+NSArray *QStringList::getNSArray() const
{
NSMutableArray *array = [NSMutableArray array];
- for (QStringList::Iterator it = begin(); it != end(); ++it) {
+ for (ConstIterator it = begin(); it != end(); ++it) {
[array addObject:(*it).getNSString()];
}
return array;
- (NSString *)renderTreeAsExternalRepresentation;
- (NSDictionary *)elementAtPoint:(NSPoint)point;
-- (NSURL *)URLWithRelativeString:(NSString *)string;
+- (NSURL *)URLWithAttributeString:(NSString *)string;
- (DOMElement *)elementWithName:(NSString *)name inForm:(DOMElement *)form;
- (DOMElement *)elementForView:(NSView *)view;
- (NSString *)incomingReferrer;
- (NSView *)viewForPluginWithURL:(NSURL *)URL
- attributes:(NSArray *)attributesArray
- baseURL:(NSURL *)baseURL
+ attributeNames:(NSArray *)attributeNames
+ attributeValues:(NSArray *)attributeValues
MIMEType:(NSString *)MIMEType;
- (NSView *)viewForJavaAppletWithFrame:(NSRect)frame
- attributes:(NSDictionary *)attributes
+ attributeNames:(NSArray *)attributeNames
+ attributeValues:(NSArray *)attributeValues
baseURL:(NSURL *)baseURL;
- (BOOL)saveDocumentToPageCache:(id)documentInfo;
return element;
}
-- (NSURL *)URLWithRelativeString:(NSString *)string
+- (NSURL *)URLWithAttributeString:(NSString *)string
{
DocumentImpl *doc = _part->xmlDocImpl();
if (!doc) {
+2004-09-20 Chris Blumenberg <cblu@apple.com>
+
+ Changes to implement renamed bridge methods.
+
+ Reviewed by darin.
+
+ * ChangeLog:
+ * DOM.subproj/WebDOMOperations.m:
+ (-[DOMDocument URLWithAttributeString:]): call renamed bridge method
+ * WebCoreSupport.subproj/WebBridge.m:
+ (-[WebBridge pluginViewWithPackage:attributeNames:attributeValues:baseURL:]): take 2 parameter arrays rather than 1 which will have to be parsed
+ (-[WebBridge viewForPluginWithURL:attributeNames:attributeValues:MIMEType:]): ditto
+
2004-09-20 Darin Adler <darin@apple.com>
Reviewed by Chris.
- (NSURL *)URLWithAttributeString:(NSString *)string
{
- return [[self _bridge] URLWithRelativeString:string];
+ return [[self _bridge] URLWithAttributeString:string];
}
@end
}
- (NSView *)pluginViewWithPackage:(WebPluginPackage *)pluginPackage
- attributes:(NSDictionary *)attributes
+ attributeNames:(NSArray *)attributeNames
+ attributeValues:(NSArray *)attributeValues
baseURL:(NSURL *)baseURL
{
WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
-
ASSERT([docView isKindOfClass:[WebHTMLView class]]);
[pluginPackage load];
WebPluginController *pluginController = [docView _pluginController];
Class viewFactory = [pluginPackage viewFactory];
+ // Store attributes in a dictionary so they can be passed to WebPlugins.
+ NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init];
+ unsigned count = [attributeNames count];
+ unsigned i;
+ for (i = 0; i < count; i++) {
+ [attributes setObject:[attributeValues objectAtIndex:i] forKey:[attributeNames objectAtIndex:i]];
+ }
+
+ NSView *view = nil;
if ([viewFactory respondsToSelector:@selector(plugInViewWithArguments:)]) {
NSDictionary *arguments = [NSDictionary dictionaryWithObjectsAndKeys:
baseURL, WebPlugInBaseURLKey,
pluginController, WebPlugInContainerKey,
nil];
LOG(Plugins, "arguments:\n%@", arguments);
- return [viewFactory plugInViewWithArguments:arguments];
+ view = [viewFactory plugInViewWithArguments:arguments];
} else if ([viewFactory respondsToSelector:@selector(pluginViewWithArguments:)]) {
NSDictionary *arguments = [NSDictionary dictionaryWithObjectsAndKeys:
baseURL, WebPluginBaseURLKey,
pluginController, WebPluginContainerKey,
nil];
LOG(Plugins, "arguments:\n%@", arguments);
- return [viewFactory pluginViewWithArguments:arguments];
- } else {
- return nil;
+ view = [viewFactory pluginViewWithArguments:arguments];
}
+ [attributes release];
+ return view;
}
-- (NSView *)viewForPluginWithURL:(NSURL *)URL
- attributes:(NSArray *)attributesArray
- baseURL:(NSURL *)baseURL
- MIMEType:(NSString *)MIMEType;
+- (NSString *)valueForKey:(NSString *)key keys:(NSArray *)keys values:(NSArray *)values
{
- NSRange r1, r2, r3;
- uint i;
-
- // Parse the attributesArray into key/value pairs.
- // Store them in a dictionary so they can be passed to WebPlugins.
- // Store them in ordered arrays so they can be passed to Netscape plug-ins.
- NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init];
- NSMutableArray *attributeKeys = [[NSMutableArray alloc] init];
- NSMutableArray *attributeValues = [[NSMutableArray alloc] init];
- for (i = 0; i < [attributesArray count]; i++) {
- NSString *attribute = [attributesArray objectAtIndex:i];
- if ([attribute rangeOfString:@"__KHTML__"].length == 0) {
- r1 = [attribute rangeOfString:@"="];
- r2 = [attribute rangeOfString:@"\""];
- r3.location = r2.location + 1;
- r3.length = [attribute length] - r2.location - 2; // don't include quotes
- NSString *key = [attribute substringToIndex:r1.location];
- NSString *value = [attribute substringWithRange:r3];
- [attributes setObject:value forKey:key];
- [attributeKeys addObject:key];
- [attributeValues addObject:value];
+ unsigned count = [keys count];
+ unsigned i;
+ for (i = 0; i < count; i++) {
+ if ([[keys objectAtIndex:i] _web_isCaseInsensitiveEqualToString:key]) {
+ return [values objectAtIndex:i];
}
}
+ return nil;
+}
+
+- (NSView *)viewForPluginWithURL:(NSURL *)URL
+ attributeNames:(NSArray *)attributeNames
+ attributeValues:(NSArray *)attributeValues
+ MIMEType:(NSString *)MIMEType
+{
+ ASSERT([attributeNames count] == [attributeValues count]);
WebBasePluginPackage *pluginPackage = nil;
NSView *view = nil;
}
}
+ NSURL *baseURL = [[[_frame dataSource] response] URL];
if (pluginPackage) {
if ([pluginPackage isKindOfClass:[WebPluginPackage class]]) {
view = [self pluginViewWithPackage:(WebPluginPackage *)pluginPackage
- attributes:attributes
+ attributeNames:attributeNames
+ attributeValues:attributeValues
baseURL:baseURL];
} else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
view = [[[WebNetscapePluginEmbeddedView alloc] initWithFrame:NSZeroRect
URL:URL
baseURL:baseURL
MIMEType:MIMEType
- attributeKeys:attributeKeys
+ attributeKeys:attributeNames
attributeValues:attributeValues] autorelease];
} else {
ASSERT_NOT_REACHED();
}
if (errorCode) {
+ NSString *pluginPage = [self valueForKey:@"pluginspage" keys:attributeNames values:attributeValues];
+ NSURL *pluginPageURL = pluginPage != nil ? [self URLWithAttributeString:pluginPage] : nil;
NSError *error = [[NSError alloc] _initWithPluginErrorCode:errorCode
contentURL:URL
- pluginPageURL:[NSURL _web_URLWithUserTypedString:[attributes objectForKey:@"pluginspage"]]
+ pluginPageURL:pluginPageURL
pluginName:[pluginPackage name]
MIMEType:MIMEType];
view = [[[WebNullPluginView alloc] initWithFrame:NSZeroRect error:error] autorelease];
[error release];
}
-
- ASSERT(view);
-
- [attributes release];
- [attributeKeys release];
- [attributeValues release];
+ ASSERT(view);
return view;
}
- (NSView *)viewForJavaAppletWithFrame:(NSRect)theFrame
- attributes:(NSDictionary *)attributes
+ attributeNames:(NSArray *)attributeNames
+ attributeValues:(NSArray *)attributeValues
baseURL:(NSURL *)baseURL;
{
NSString *MIMEType = @"application/x-java-applet";
if (pluginPackage) {
if ([pluginPackage isKindOfClass:[WebPluginPackage class]]) {
- NSMutableDictionary *theAttributes = [NSMutableDictionary dictionary];
- [theAttributes addEntriesFromDictionary:attributes];
- [theAttributes setObject:[NSString stringWithFormat:@"%d", (int)theFrame.size.width] forKey:@"width"];
- [theAttributes setObject:[NSString stringWithFormat:@"%d", (int)theFrame.size.height] forKey:@"height"];
-
+ // For some reason, the Java plug-in requires that we pass the dimension of the plug-in as attributes.
+ NSMutableArray *names = [attributeNames mutableCopy];
+ NSMutableArray *values = [attributeValues mutableCopy];
+ if ([self valueForKey:@"width" keys:attributeNames values:attributeValues] == nil) {
+ [names addObject:@"width"];
+ [values addObject:[NSString stringWithFormat:@"%d", (int)theFrame.size.width]];
+ }
+ if ([self valueForKey:@"height" keys:attributeNames values:attributeValues] == nil) {
+ [names addObject:@"height"];
+ [values addObject:[NSString stringWithFormat:@"%d", (int)theFrame.size.height]];
+ }
view = [self pluginViewWithPackage:(WebPluginPackage *)pluginPackage
- attributes:theAttributes
+ attributeNames:names
+ attributeValues:values
baseURL:baseURL];
+ [names release];
+ [values release];
} else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
- // Convert the attributes dictionary to 2 string arrays because this is what Netscape plug-ins expect.
- NSMutableArray *attributeKeys = [[NSMutableArray alloc] init];
- NSMutableArray *attributeValues = [[NSMutableArray alloc] init];
- NSEnumerator *enumerator = [attributes keyEnumerator];
- NSString *key;
-
- while ((key = [enumerator nextObject]) != nil) {
- [attributeKeys addObject:key];
- [attributeValues addObject:[attributes objectForKey:key]];
- }
view = [[[WebNetscapePluginEmbeddedView alloc] initWithFrame:theFrame
plugin:(WebNetscapePluginPackage *)pluginPackage
URL:nil
baseURL:baseURL
MIMEType:MIMEType
- attributeKeys:attributeKeys
+ attributeKeys:attributeNames
attributeValues:attributeValues] autorelease];
- [attributeKeys release];
- [attributeValues release];
} else {
ASSERT_NOT_REACHED();
}